ç®æ¬¡
- èšäº1
- ããŒã1.ã²ãŒã ãµã€ã¯ã«
- ããŒã2.ã©ã€ãã©ãª
- ããŒã3.éšå±ãšãšãªã¢
- ããŒã4.æŒç¿
- ã»ã¯ã·ã§ã³2
- ããŒã5.ã²ãŒã ã®åºæ¬
- ããŒã6.ãã¬ãŒã€ãŒã¯ã©ã¹ã®åºæ¬
- ã»ã¯ã·ã§ã³3
- ããŒã7.ãã¬ãŒã€ãŒã®ãã©ã¡ãŒã¿ãŒã𿻿
- ããŒã8.æµ
- ã»ã¯ã·ã§ã³4
- ããŒã9.ãã£ã¬ã¯ã¿ãŒãšã²ãŒã ãµã€ã¯ã«
- ããŒã10.ã³ãŒãäœæã®ãã©ã¯ãã£ã¹
- ããŒã11.ååçã¹ãã«
- ã»ã¯ã·ã§ã³5
- ããŒã12.ãã®ä»ã®ååçã¹ãã«
13.ã¹ãã«ããªãŒ
14.ã³ã³ãœãŒã«
15.æçµ
ããŒã7ïŒãã¬ãŒã€ãŒã®ãªãã·ã§ã³ã𿻿
ã¯ããã«
ãã®éšåã§ã¯ããã¬ãŒã€ãŒã«é¢é£ããã²ãŒã ãã¬ã€ã®éšåã«çŠç¹ãåœãŠãŸãã ãŸããæãåºæ¬çãªãã©ã¡ãŒã¿ãŒã§ãã匟è¬ãå éããã«ã¹ïŒHPïŒãããã³ã¹ãã«ãã€ã³ãã远å ããŸãã ãããã®ãã©ã¡ãŒã¿ãŒã¯ã²ãŒã å
šäœã§äœ¿çšããããã¬ãŒã€ãŒã䜿çšå¯èœãªãã¹ãŠã®ã¢ã¯ã·ã§ã³ãå®è¡ããããã«äœ¿çšããäž»ãªãã©ã¡ãŒã¿ãŒã§ãã ãã®åŸããªãœãŒã¹ãªããžã§ã¯ããã€ãŸããã¬ãŒã€ãŒãåéã§ãããªããžã§ã¯ãã®äœæã«é²ã¿ãŸãã ãããã«ã¯äžèšã®ãã©ã¡ãŒã¿ãŒãå«ãŸããŠããŸãã ãããŠæåŸã«ãæ»æã·ã¹ãã ãšããã€ãã®ç°ãªããã¬ã€ã€ãŒæ»æã远å ããŸãã
æç»é åº
ã²ãŒã ã®äž»èŠéšåã«ç§»ãåã«ãç§ãèŠèœãšããŠãããã1ã€ã®éèŠãªåŽé¢ãã€ãŸãæç»é åºãèæ
®ããå¿
èŠããããŸãã
æç»é åºã¯ãäžããæç»ãããªããžã§ã¯ããšäžããæç»ãããªããžã§ã¯ããæ±ºå®ããŸãã ããšãã°ãç¹å®ã®ã€ãã³ããå®è¡ããããšãããã€ãã®ãšãã§ã¯ããã¬ã³ããªã³ã°ãããŸãã ãã¬ãŒã€ãŒã®äžãªã©ãä»ã®ãªããžã§ã¯ãã®äžã«ãšãã§ã¯ããæç»ãããå Žåããããã¯è¡šç€ºãããªãããæ£ãã衚瀺ãããŸããã ãããã£ãŠãããããåžžã«ä»ã®ãã¹ãŠã®äžã«æç»ãããããã«ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãæç»ãªããžã§ã¯ãã®é åºãèšå®ããå¿
èŠããããŸãã
ãã®åé¡ã解決ããæ¹æ³ã¯ããªãç°¡åã§ãã
GameObject
ã¯ã©ã¹ã§ã¯ãæåã¯ãã¹ãŠã®ãšã³ãã£ãã£ã«å¯ŸããŠ50ã§ãã
depth
屿§ãå®çŸ©ãããã®åŸãåã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒå®çŸ©ã§ããªãã·ã§ã³ã§ãªããžã§ã¯ãã®åã¯ã©ã¹ã®
depth
屿§ãåå¥ã«èšå®ã§ããŸãã èãã¯ãããæ·±ããªããžã§ã¯ãã¯äžã«æç»ããæ·±ãã¯ããäžã«æç»ããããšã§ãã ã€ãŸããããšãã°ãä»ã®ãã¹ãŠã®äžã«ãã¹ãŠã®å¹æãæç»ããå Žåãå€75ãªã©ã®
depth
屿§ã«åçŽã«å²ãåœãŠãããšãã§ããŸãã
function TickEffect:new(area, x, y, opts) TickEffect.super.new(self, area, x, y, opts) self.depth = 75 ... end
å
éšã§ã¯ã次ã®ããã«æ©èœããŸããåãã¬ãŒã ã§ãåãªããžã§ã¯ãã®
depth
屿§ã§
game_objects
ã®ãªã¹ãããœãŒãããŸãã
function Area:draw() table.sort(self.game_objects, function(a, b) return a.depth < b.depth end) for _, game_object in ipairs(self.game_objects) do game_object:draw() end end
ããã§ã¯ãã¬ã³ããªã³ã°ã®åã«ã
table.sort
ã䜿çšããŠã
depth
屿§ã§ãšã³ãã£ãã£ãäžŠã¹æ¿ããŸãã æ·±ããå°ãããšã³ãã£ãã£ã¯ããŒãã«ã®åé¢ã«ç§»åããŸããã€ãŸããæåã«ïŒä»ã®ãã¹ãŠã®äžã«ïŒæç»ãããæ·±ãã倧ãããšã³ãã£ãã£ã¯ããŒãã«ã®æåŸã«ç§»åããæåŸã«ïŒäžã«ïŒæç»ãããŸãã ç°ãªãçš®é¡ã®ãªããžã§ã¯ãã«ç°ãªãæ·±ããèšå®ããããšãããšããããæ©èœããããšãããããŸãã
ãã®ã¢ãããŒãã§ã¯ã1ã€ã®å°ããªåé¡ãçºçããŸããäžéšã®ãªããžã§ã¯ãã¯åãæ·±ããæã¡ããããçºçãããšã
game_objects
ããŒãã«ãçµ¶ãããœãŒãããããšãã«
game_objects
ãçºçããå Žåã
game_objects
ãŸãã ãªããžã§ã¯ãã®å¥¥è¡ããåãå Žåããããã¬ãŒã ã§ã¯1ã€ã®ãªããžã§ã¯ããå¥ã®ãªããžã§ã¯ãã®äžã«è¡šç€ºãããŸãããæ¬¡ã®ãã¬ãŒã ã§ã¯ãã®äžã«è¡šç€ºããããããã¡ãã€ããçºçããŸãã ããã®å¯èœæ§ã¯å°ããã§ãããããã¯èµ·ããå¯èœæ§ãããããããé²ãå¿
èŠããããŸãã
ããã解決ãã1ã€ã®æ¹æ³ã¯ããªããžã§ã¯ãã®æ·±ããåãå Žåã«å¥ã®ãœãŒããã©ã¡ãŒã¿ãŒãå®çŸ©ããããšã§ãã ç§ãã¡ã®å Žåãå¥ã®ãã©ã¡ãŒã¿ãŒãšããŠãªããžã§ã¯ãäœææéãéžæããŸããã
function Area:draw() table.sort(self.game_objects, function(a, b) if a.depth == b.depth then return a.creation_time < b.creation_time else return a.depth < b.depth end end) for _, game_object in ipairs(self.game_objects) do game_object:draw() end end
ã€ãŸããæ·±ããåãå Žåã以åã«äœæããããªããžã§ã¯ããå
ã«æç»ãããåŸã§äœæãããŸãã ããã¯è«ççãªè§£æ±ºçã§ããããã¹ããããšæ©èœããããšãããããŸãã
æç»é åºã®æŒç¿
93.ãªããžã§ã¯ãã®é åºã倿ŽããŠã奥ã®ã»ãã奥ã«ãå¥¥ã®æ¹ãå¥¥ã«æç»ãããããã«ããŸãã ãªããžã§ã¯ãã®æ·±ããåãå Žåã¯ãäœææéé ã«äžŠã¹æ¿ããå¿
èŠããããŸãã åã«äœæãããªããžã§ã¯ããæåŸã«æç»ããåŸã§äœæãããªããžã§ã¯ããæåã«æç»ããå¿
èŠããããŸãã
94.以äžã«ç€ºããããªäžé¢ã®2.5Dã²ãŒã ã§ã¯ããšã³ãã£ãã£ãé©åãªé åºã§ã¬ã³ããªã³ã°ãããã€ãŸãäœçœ®
y
ã§ãœãŒãããå¿
èŠããããŸãã yå€ã倧ããïŒã€ãŸããç»é¢ã®äžéšã«è¿ãïŒãšã³ãã£ãã£ãæåŸã«æç»ããyå€ãå°ãããšã³ãã£ãã£ãæåã«æç»ããå¿
èŠããããŸãã ãã®å ŽåããœãŒãæ©èœã¯ã©ã®ããã«ãªããŸããïŒ
äž»ãªãã©ã¡ãŒã¿ãŒ
次ã«ããã©ã¡ãŒã¿ãŒã®äœæãéå§ããŸãã æåã«ç¢ºèªãããã©ã¡ãŒã¿ãŒã¯ããŒã¹ãã§ãã ãã¬ã€ã€ãŒããäžããŸãã¯ãäžããæŒããšãè¹ã¯æŒãããããŒã«å¿ããŠé床ã倿ŽããŸãã ãã®åºæ¬æ©èœã«å ããŠãã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã䜿çšãããšæ¯æžããã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã䜿çšããªããšåŸã
ã«åŸ©å
ããããªãœãŒã¹ãå¿
èŠã§ãã æ¬¡ã®å€ãšã«ãŒã«ãé©çšããŸãã
- ãã¬ã€ã€ãŒã¯æåã«100åäœã®å éãæã¡ãŸã
- å é床ã䜿çšãããšãå é床ã50åäœæžå°ããŸã
- æ¯ç§10åã®å éåäœãåžžã«çæãããŸã
- å éåäœã®æ°ã0ã«éãããšããã®ããããã£ã¯ãã¯ãŒã«ããŠã³ãããŠåã³äœ¿çšã§ããããã«ãªããŸã§2ç§ããããŸãã
- å éã¯ããå·åŽããç¡å¹ã§ãå éãŠãããã®ãªãœãŒã¹ã0ãã倧ããå Žåã«ã®ã¿å®è¡ã§ããŸã
ã«ãŒã«ã¯å°ãè€éã«èŠããŸãããæ¬åœã«ç°¡åã§ãã æåã®3ã€ã¯æ°å€ã®ã¿ã¹ã¯ã§ãããæåŸã®2ã€ã¯ç¡éã®å éãé²ãããã«å¿
èŠã§ãã ãªãœãŒã¹ã0ã«éãããšãåžžã«1ã«å埩ããŸããããã«ããããã¬ãŒã€ãŒãçµ¶ããå éã䜿çšããç¶æ³ãçºçããå¯èœæ§ããããŸãã ãã®ç¶æ³ãé²ãã«ã¯ããå·åŽããå¿
èŠã§ãã
次ã«ããããã³ãŒãã«è¿œå ããŸãã
function Player:new(...) ... self.max_boost = 100 self.boost = self.max_boost end function Player:update(dt) ... self.boost = math.min(self.boost + 10*dt, self.max_boost) ... end
ããã«ãããã«ãŒã«1ããã³3ãå®è£
ããŸããæåã«ã
boost
ã®å€ã¯
max_boost
ãã€ãŸã100ã§ãããå€
max_boost
ãŸã§ã1ç§ããã10ã远å ããŠ
boost
ããŸãã ãŸãããã¬ãŒã€ãŒãå éãããšãã«æ¯ç§50ãŠããããåŒãã ãã§ãã«ãŒã«2ãå®è£
ã§ããŸãã
function Player:update(dt) ... if input:down('up') then self.boosting = true self.max_v = 1.5*self.base_max_v self.boost = self.boost - 50*dt end if input:down('down') then self.boosting = true self.max_v = 0.5*self.base_max_v self.boost = self.boost - 50*dt end ... end
ãã®ã³ãŒãã®äžéšã¯ãã§ã«ããã«ãããŸãããã€ãŸãã远å ãããè¡ã¯
self.boost -= 50*dt
ã§ããã ããã§ãã«ãŒã«4ã確èªããã«ã¯ã
boost
ã0ã«éãããšãã«å·åŽã2ç§ééå§ãããããšã確èªããå¿
èŠããããŸãã ããã§ã¯ããå€ãã®å¯åéšåã䜿çšããããããããã¯å°ãè€éã§ãã ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
function Player:new(...) ... self.can_boost = true self.boost_timer = 0 self.boost_cooldown = 2 end
ãŸãã3ã€ã®å€æ°ã玹ä»ããŸãã
can_boost
ã¯ãå éãå®è¡ã§ããã¿ã€ãã³ã°ãå ±åããããã«äœ¿çšãããŸãã ãã¬ãŒã€ãŒã¯ã²ãŒã ã®éå§æã«å éã§ããå¿
èŠããããããããã©ã«ãã§ã¯trueã§ãã
boost
ã0ã«éãããšfalseã«èšå®ããã
boost_cooldown
ç§åŸã«trueã«èšå®ãããŸãã
boost_timer
倿°ã¯ã
boost
ã0ã«ãªã£ãŠããçµéããæéã
boost_cooldown
ããã®å€æ°ã
boost_cooldown
ãè¶
ãããšã
can_boost
ã¯trueã«èšå®ãããŸãã
function Player:update(dt) ... self.boost = math.min(self.boost + 10*dt, self.max_boost) self.boost_timer = self.boost_timer + dt if self.boost_timer > self.boost_cooldown then self.can_boost = true end self.max_v = self.base_max_v self.boosting = false if input:down('up') and self.boost > 1 and self.can_boost then self.boosting = true self.max_v = 1.5*self.base_max_v self.boost = self.boost - 50*dt if self.boost <= 1 then self.boosting = false self.can_boost = false self.boost_timer = 0 end end if input:down('down') and self.boost > 1 and self.can_boost then self.boosting = true self.max_v = 0.5*self.base_max_v self.boost = self.boost - 50*dt if self.boost <= 1 then self.boosting = false self.can_boost = false self.boost_timer = 0 end end self.trail_color = skill_point_color if self.boosting then self.trail_color = boost_color end end
ããã¯è€éã«æããŸãããã³ãŒãã¯ç§ãã¡ãéæãããã£ããã®ãåã«å®è£
ããŠããŸãã
input:down
ã§ããŒãæŒããããã©ããããã§ãã¯ãã代ããã«ã
boost
1ããäžïŒã«ãŒã«5ïŒã§ããã
can_boost
ãtrueïŒã«ãŒã«5ïŒã§ããããšããã§ãã¯ããŸãã
boost
ã0ã«éãããã
can_boost
ããã³
can_boost
倿°ãfalseã«èšå®ãã
boost_timer
ã0ã«ãªã»ããããŸã
boost_timer
ã¯åãã¬ãŒã ã§
boost_timer
ã«è¿œå ããã
boost_timer
ã2ç§åŸã«
can_boost
ãtrueã«èšå®ããåã³å éã§ããŸãïŒã«ãŒã«4ïŒã
äžèšã®ã³ãŒãã¯ãå®äºç¶æ
ã®å éã¡ã«ããºã ã§ãã ããã§ã¯ããã®ã³ãŒããããç¡ç§©åºã§ãæªã決å®ãçµã¿åãããŠåŒã³åºãããšãã§ããããšã«æ³šæããŠãã ããã ããããããã¯ãŸãã«ã²ãŒã ãã¬ã€ã®ç¹å®ã®åŽé¢ãåŠçããã³ãŒãã®ã»ãšãã©ãã©ã®ããã«èŠãããã§ãã ããã§ã¯ãããã€ãã®ã«ãŒã«ã«åŸããšåæã«ãããã«åŸãå¿
èŠããããŸãã ãã®ãããªã³ãŒãã«æ
£ããå¿
èŠãããããã«æããŸãã
ãã¹ãŠã®äž»èŠãªãã©ã¡ãŒã¿ãŒã®ãã¡ãå éã ãã§ãè€éãªããžãã¯ãæã£ãŠããå¯èœæ§ããããŸãã 匟è¬ãšHPã®2ã€ã®éèŠãªãªãã·ã§ã³ããããŸãããã©ã¡ããã¯ããã«ç°¡åã§ãã 匟è¬ã¯ãã¬ã€ã€ãŒã®æ»æäžã«æ¶è²»ãããã²ãŒã äžã«ãªãœãŒã¹ãåéããããšåŸ©å
ããããã¬ã€ã€ãŒããã¡ãŒãžãåãããšHPãæžå°ãããªãœãŒã¹ãåéããããšåŸ©å
ãããŸãã ããã§ãã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã§è¡ã£ãããã«ãããããã¡ã€ã³ãã©ã¡ãŒã¿ãšããŠåçŽã«è¿œå ã§ããŸãã
function Player:new(...) ... self.max_hp = 100 self.hp = self.max_hp self.max_ammo = 100 self.ammo = self.max_ammo end
è³æº
ç§ã¯ãäž»èŠãªãã©ã¡ãŒã¿ãŒã®1ã€ã«åœ±é¿ãããªãœãŒã¹ãå°ããªãªããžã§ã¯ããšåŒã³ãŸãã ã²ãŒã ã«ã¯ããã®ãããªãªããžã§ã¯ãã5çš®é¡ãããæ¬¡ã®ããã«æ©èœããŸãã
- 匟è¬ãªãœãŒã¹ã¯ãã¬ã€ã€ãŒã®5åã®åŒŸè¬ã埩å
ããæµãæ»ãã ãšãã«äœæãããŸã
- å éãªãœãŒã¹ã¯ããã¬ã€ã€ãŒã®25åã®å éãŠãããã埩å
ãããã£ã¬ã¯ã¿ãŒã«ãã£ãŠã©ã³ãã ã«äœæãããŸã
- HPãªãœãŒã¹ã¯ããã¬ãŒã€ãŒãã25 HPã埩å
ãããã£ã¬ã¯ã¿ãŒã«ãã£ãŠã©ã³ãã ã«äœæãããŸãã
- SkillPointãªãœãŒã¹ã¯ããã¬ãŒã€ãŒã«1ã€ã®ã¹ãã«ãã€ã³ãã远å ãããã£ã¬ã¯ã¿ãŒã«ãã£ãŠã©ã³ãã ã«äœæãããŸãã
- æ»æãªãœãŒã¹ã¯ããã¬ãŒã€ãŒã®çŸåšã®æ»æã倿Žãããã£ã¬ã¯ã¿ãŒã«ãã£ãŠã©ã³ãã ã«äœæãããŸã
ãã£ã¬ã¯ã¿ãŒïŒãã£ã¬ã¯ã¿ãŒïŒ-æµãšãªãœãŒã¹ã®äœæãå¶åŸ¡ããã³ãŒãã ä»ã®ã²ãŒã ïŒL4Dãªã©ïŒã§ãã®ãããªååãä»ããããŠãããé©åã ãšæãããããããããåŒã³åºããŸããã ã³ãŒãã®ãã®éšåã§äœæ¥ããã€ããã¯ãªãã®ã§ãåãªãœãŒã¹ã®äœæãããŒã«é¢é£ä»ããŠãäœæ¥ãç°¡åã«ãã¹ãããŸãã
匟è¬ãªãœãŒã¹
匟è¬ããå§ããŸãããã æçµçµæã¯æ¬¡ã®ããã«ãªããŸãã
å°ããªç·è²ã®é·æ¹åœ¢ã¯åŒŸè¬ã®è³æºã§ãã ãã¬ã€ã€ãŒã圌ã«è§ŠãããšããªãœãŒã¹ãç Žå£ããããã¬ã€ã€ãŒã¯5ãŠãããã®åŒŸè¬ãåãåããŸãã æ°ãã
Ammo
ã¯ã©ã¹ãäœæããå®çŸ©ããå§ããããšãã§ããŸãã
function Ammo:new(...) ... self.w, self.h = 8, 8 self.collider = self.area.world:newRectangleCollider(self.x, self.y, self.w, self.h) self.collider:setObject(self) self.collider:setFixedRotation(false) self.r = random(0, 2*math.pi) self.v = random(10, 20) self.collider:setLinearVelocity(self.v*math.cos(self.r), self.v*math.sin(self.r)) self.collider:applyAngularImpulse(random(-24, 24)) end function Ammo:draw() love.graphics.setColor(ammo_color) pushRotate(self.x, self.y, self.collider:getAngle()) draft:rhombus(self.x, self.y, self.w, self.h, 'line') love.graphics.pop() love.graphics.setColor(default_color) end
匟è¬ãªãœãŒã¹ã¯ãæåã¯
setLinearVelocity
ããã³
applyAngularImpulse
ã«ãã£ãŠèšå®ããããã©ã³ãã ãªäœéããã³å転ã§äœæãããç©ççãªé·æ¹åœ¢ã§ãã ããã«ããã®ãªããžã§ã¯ãã¯
draft
ã©ã€ãã©ãªã䜿çšããŠã¬ã³ããªã³ã°ãããŸãã ããã¯ãèªåã§è¡ãããã䟿å©ã«ããããçš®é¡ã®å³åœ¢ãæç»ã§ããå°ããªã©ã€ãã©ãªã§ãã ç§ãã¡ã®å ŽåãåçŽã«ä»»æã®é·æ¹åœ¢ã®ããã«ãªãœãŒã¹ãæç»ã§ããŸããããã®æ¹æ³ã§è¡ãããšã«ããŸããã ã©ã€ãã©ãªãèªåã§ã€ã³ã¹ããŒã«ããããã¥ã¡ã³ããèªã¿ããã®æ©èœã«ã€ããŠåŠç¿ããŠããããšãåæãšããŸãã ããã«ã
getAngle
ã®çµæã䜿çšããŠãç©çãªããžã§ã¯ãã®å転ãèæ
®ããŸãã
ããããã¹ãŠãã¹ãããããã«ããããã®ãªããžã§ã¯ãã®ããããã®äœæãããŒã«ãã€ã³ãã§ããŸãã
function Stage:new() ... input:bind('p', function() self.area:addGameObject('Ammo', random(0, gw), random(0, gh)) end) end
ããã§ã²ãŒã ãéå§ããŠPãæ°åæŒããšããªããžã§ã¯ãã®äœææ¹æ³ãšç§»å/å転ã衚瀺ãããŸãã
次ã«äœæããå¿
èŠãããã®ã¯ããã¬ãŒã€ãŒãšãªãœãŒã¹éã®è¡çªã®çžäºäœçšã§ãã ãã®çžäºäœçšã¯ãã¹ãŠã®ãªãœãŒã¹ã«äœ¿çšãããã»ãšãã©åžžã«åãã§ãã æåã«è¡ãããšã¯ããã¬ã€ã€ãŒã®ç©çãªããžã§ã¯ããšç©ç匟è¬ãªããžã§ã¯ãã®è¡çªã€ãã³ããã€ã³ã¿ãŒã»ããããããšã§ãã ãããå®è£
ããæãç°¡åãªæ¹æ³ã¯ã
(collision classes)
ã䜿çšãã
(collision classes)
ã§ãã ãŸããæ¢åã®ãªããžã§ã¯ãã®è¡çªã®3ã€ã®ã¯ã©ã¹ãå®çŸ©ã§ããŸãïŒãã¬ãŒã€ãŒãçºå°ç©ãããã³ãªãœãŒã¹ã
function Stage:new() ... self.area = Area(self) self.area:addPhysicsWorld() self.area.world:addCollisionClass('Player') self.area.world:addCollisionClass('Projectile') self.area.world:addCollisionClass('Collectable') ... end
ãããŠããããã®åãã¡ã€ã«ïŒPlayerãProjectileãAmmoïŒã§ã¯ã
setCollisionClass
ã䜿çšããŠè¡çªåè¡çªã¯ã©ã¹ãèšå®ã§ããŸãïŒä»ã®ãã¡ã€ã«ã§ãã®ã³ãŒããç¹°ãè¿ããŸãïŒã
function Player:new(...) ... self.collider:setCollisionClass('Player') ... end
ããèªäœã¯äœã倿Žãããç©çãªããžã§ã¯ãéã®è¡çªã®ã€ãã³ããã€ã³ã¿ãŒã»ããã§ããåºç€ãäœæããŸãã ããšãã°ãã³ãªãžã§ã³ã¯ã©ã¹
Collectable
ã倿ŽããŠ
Player
ç¡èŠããå ŽåïŒ
self.area.world:addCollisionClass('Collectable', {ignores = {'Player'}})
ã²ãŒã ãéå§ãããšããã¬ã€ã€ãŒã匟è¬ãªãœãŒã¹ãªããžã§ã¯ããç©ççã«ç¡èŠããããšã«æ°ä»ãã§ãããã ããã¯ç§ãã¡ãç®æããŠãããã®ã§ã¯ãããŸããããè¡çªã¯ã©ã¹ã§ã§ããããšã®è¯ãäŸãšããŠåœ¹ç«ã¡ãŸãã ããã3ã€ã®è¡çªã¯ã©ã¹ã¯ã次ã®èŠåã«åŸãå¿
èŠããããŸãã
- çºå°ç©ã¯çºå°ç©ãç¡èŠããŸã
- Collectableã¯Collectableãç¡èŠããŸã
- åéç©ã¯çºå°ç©ãç¡èŠããŸã
- Playerã¯Collectableã§è¡çªã€ãã³ããçæããŸã
ã«ãŒã«1ã2ã3ã¯ã
addCollisionClass
åŒã³åºãã«å°ããªå€æŽãå ããããšã§å®è£
ã§ããŸãã
function Stage:new() ... self.area.world:addCollisionClass('Player') self.area.world:addCollisionClass('Projectile', {ignores = {'Projectile'}}) self.area.world:addCollisionClass('Collectable', {ignores = {'Collectable', 'Projectile'}}) ... end
è¡çªã¯ã©ã¹ã宣èšããé åºãéèŠã§ããããšã¯æ³šç®ã«å€ããŸãã ããšãã°ãProjectileã¯ã©ã¹ãšCollectableã¯ã©ã¹ã®å®£èšãå
¥ãæ¿ãããšãCollectableè¡çªã¯ã©ã¹ãProjectileè¡çªã¯ã©ã¹ãžã®ãªã³ã¯ãäœæãããããProjectileè¡çªã¯ã©ã¹ããŸã å®çŸ©ãããŠããªããããšã©ãŒãçºçããŸãã
4çªç®ã®ã«ãŒã«ã¯ã
enter
ãåŒã³åºãããšã§å®è£
ã§ããŸãã
function Player:update(dt) ... if self.collider:enter('Collectable') then print(1) end end
ã³ãŒããå®è¡ãããšããã¬ãŒã€ãŒã匟è¬ãªãœãŒã¹ãšè¡çªãããã³ã«ãã³ã³ãœãŒã«ã«1ã衚瀺ãããŸãã
Ammo
ã¯ã©ã¹ã«è¿œå ããå¿
èŠã®ãããã1ã€ã®èŠçŽ ã¯ããã¬ãŒã€ãŒãžã®ãªããžã§ã¯ãã®ãã£ããããåãã§ãã ãããè¡ãæãç°¡åãªæ¹æ³ã¯ã
Seek Behavioråäœã远å ããããšã§ãã ã·ãŒã¯åäœã®ç§ã®ããŒãžã§ã³ã¯
ãExampleã«
ããProgramming Game AIã®æžç±ã«åºã¥ããŠããŸããããã«ã¯ãäžè¬çãªå¶åŸ¡åäœã®éåžžã«åªããéžæããããŸãã æ£çŽãªãšãããã©ã®ããã«åäœããã®ãèŠããŠããªãã®ã§ãåäœã®è©³çްã¯èª¬æããŸããããããã£ãŠãèå³ãããå Žåã¯èªåã§çè§£ããŠãã ããïŒD
function Ammo:update(dt) ... local target = current_room.player if target then local projectile_heading = Vector(self.collider:getLinearVelocity()):normalized() local angle = math.atan2(target.y - self.y, target.x - self.x) local to_target_heading = Vector(math.cos(angle), math.sin(angle)):normalized() local final_heading = (projectile_heading + 0.1*to_target_heading):normalized() self.collider:setLinearVelocity(self.v*final_heading.x, self.v*final_heading.y) else self.collider:setLinearVelocity(self.v*math.cos(self.r), self.v*math.sin(self.r)) end end
ããã§ã匟è¬ãªãœãŒã¹ãååšããå Žåã
target
ã«åããããŸããããã§ãªãå ŽåããªãœãŒã¹ã¯æåã«æå®ãããæ¹åã«ç§»åããŸãã
target
ã¯ã次ã®ããã«
Stage
ã§èšå®ããããã¬ãŒã€ãŒãžã®ãªã³ã¯ãå«ãŸããŸãã
function Stage:new() ... self.player = self.area:addGameObject('Player', gw/2, gh/2) end
æ®ã£ãŠããã®ã¯ã匟è¬ãªãœãŒã¹ãåéããããšãã«çºçããã¢ã¯ã·ã§ã³ãåŠçããããšã ãã§ãã äžèšã®gifã¢ãã¡ãŒã·ã§ã³ã§ã¯ãããŒãã£ã¯ã«ã§å°ããªå¹æãåçŸããïŒçºå°äœããæ»ã¬ããšãã®å¹æã«äŒŒãŠããŸãïŒããã¬ã€ã€ãŒã¯+5ã®åŒŸè¬ãåãåããŸãã
ãšãã§ã¯ãããå§ããŸãããã ãã®ãšãã§ã¯ãã¯ã
ProjectileDeathEffect
ãªããžã§ã¯ããšåãããžãã¯ã䜿çšããŸããå°ããªçœãéå
ãçºçãããšãã§ã¯ãã®å®éã®è²ã衚瀺ãããŸãã ããã§ã®å¯äžã®éãã¯ãæ£æ¹åœ¢ãæç»ãã代ããã«ãè±åœ¢ãã€ãŸãã匟è¬ãªãœãŒã¹èªäœãæç»ããããã«äœ¿çšããã®ãšåãå³ãæç»ããããšã§ãã ãã®æ°ãã
AmmoEffect
ãªããžã§ã¯ãã«ååã
AmmoEffect
ãŸãã
ProjectileDeathEffect
䌌ãŠãããããè©³çŽ°ã«æ€èšããŸããã ãã ããæ¬¡ã®ããã«åŒã³åºããŸãã
function Ammo:die() self.dead = true self.area:addGameObject('AmmoEffect', self.x, self.y, {color = ammo_color, w = self.w, h = self.h}) for i = 1, love.math.random(4, 8) do self.area:addGameObject('ExplodeParticle', self.x, self.y, {s = 3, color = ammo_color}) end end
ããã§ã¯ã1ã€ã®
AmmoEffect
ãªããžã§ã¯ããäœæããŠããã
AmmoEffect
åã®
AmmoEffect
ãªããžã§ã¯ããäœæããŸãããããã¯ãPlayerã®ãã¹ãšãã§ã¯ãã§æ¢ã«äœ¿çšããŠããŸãã Ammoãªããžã§ã¯ãã®
die
颿°ã¯ãPlayerãšè¡çªãããšãã«åŒã³åºãããŸãïŒ
function Player:update(dt) ... if self.collider:enter('Collectable') then local collision_data = self.collider:getEnterCollisionData('Collectable') local object = collision_data.collider:getObject() if object:is(Ammo) then object:die() end end end
ããã§ã¯ããŸã
getEnterCollisionData
ã䜿çšããŠãæå®ããã©ãã«ã®æåŸã®ãšã³ã¿ãŒã³ãªãžã§ã³ã€ãã³ãã«ãã£ãŠçæãããã³ãªãžã§ã³ããŒã¿ãååŸããŸãã æ¬¡ã«ã
getObject
ã䜿çšããŠãCollisibleã€ãã³ãã«åå ããã³ã©ã€ããŒã«ã¢ã¿ããããããªããžã§ã¯ããžã®ã¢ã¯ã»ã¹ãååŸããŸã
getObject
ã€ãã³ãã«ã¯ãCollectableè¡çªã¯ã©ã¹ã®ä»»æã®ãªããžã§ã¯ããæå®ã§ããŸãã ç§ãã¡ã®å ŽåãAmmoãªããžã§ã¯ããããããŸããããä»ã®ãã®ãããå Žåã¯ãããããåºå¥ããã³ãŒããé
眮ãããå Žæã§ãã ãããŠãããããŸãã«ç§ãã¡ããã£ãŠããããšã§ã
getObject
ããåãåã£ããªããžã§ã¯ãã
Ammo
ã¯ã©ã¹ãã©ããã確èªããããã«ãã¯ã©ã·ãã¯ã©ã€ãã©ãªã®
is
颿°ã䜿çšããŸãã ãããå®éã«åŒŸè¬ã¯ã©ã¹ã®ãªããžã§ã¯ãã§ããå Žåããã®
die
颿°ãåŒã³åºããŸãã æ¬¡ã®ããã«ãªããŸãã
æåŸã«å¿ããã®ã¯ã匟è¬ãªãœãŒã¹ãåéãããšãã«ãã¬ã€ã€ãŒã«åŒŸè¬+5ã远å ããããšã§ãã ãããè¡ãã«ã¯ã
addAmmo
颿°ãå®çŸ©ããŸãããã®é¢æ°ã¯ãç¹å®ã®å€ãåçŽã«
ammo
倿°ã«è¿œå ãã
max_ammo
è¶
ããªãããšã
max_ammo
ãŸãã
function Player:addAmmo(amount) self.ammo = math.min(self.ammo + amount, self.max_ammo) end
ãããŠããã®é¢æ°ã
object:die()
åŸã«è¿œå ããŸãã
å éãªãœãŒã¹ïŒããŒã¹ãïŒ
ããã§ã¯ãé床ã«ã€ããŠèª¬æããŸãããã æçµçµæã¯æ¬¡ã®ããã«ãªããŸãã
ã芧ã®ãšãããã¢ã€ãã¢ã¯åŒŸè¬ãªãœãŒã¹ãšã»ãŒåãã§ãããŒã¹ããªãœãŒã¹ã®åãããããã«ç°ãªããèŠãç®ãå°ãç°ãªãããªãœãŒã¹ãåéããããšãã«åçŸãããèŠèŠå¹æãç°ãªããŸãã
äž»ãªãã®ããå§ããŸãããã 匟è¬ãé€ããã¹ãŠã®ãªãœãŒã¹ã¯ãç»é¢ã®å·ŠåŽãŸãã¯å³åŽã«äœæããããã£ãããšå察åŽã«çŽç·çã«ç§»åããŸãã åãããšãæµã«ãåœãŠã¯ãŸããŸãã ããã«ããããã¬ãŒã€ãŒã¯ãªãœãŒã¹ã«ç§»åããå¿
èŠã«å¿ããŠãªãœãŒã¹ãåéããã®ã«ååãªæéã確ä¿ã§ããŸãã
Boost
ã¯ã©ã¹ã®ã¡ã€ã³ã®åæã³ãŒãã¯
Ammo
ã¯ã©ã¹ãšã»ãŒåãã§ãã æ¬¡ã®ããã«ãªããŸãã
function Boost:new(...) ... local direction = table.random({-1, 1}) self.x = gw/2 + direction*(gw/2 + 48) self.y = random(48, gh - 48) self.w, self.h = 12, 12 self.collider = self.area.world:newRectangleCollider(self.x, self.y, self.w, self.h) self.collider:setObject(self) self.collider:setCollisionClass('Collectable') self.collider:setFixedRotation(false) self.v = -direction*random(20, 40) self.collider:setLinearVelocity(self.v, 0) self.collider:applyAngularImpulse(random(-24, 24)) end function Boost:update(dt) ... self.collider:setLinearVelocity(self.v, 0) end
ãã ããããã€ãã®éãããããŸããã³ã³ã¹ãã©ã¯ã¿ãŒã®æåã®3è¡ã¯ããªããžã§ã¯ãã®éå§äœçœ®ãååŸããŸãã颿°ã¯æ¬¡ã®ããã«table.random
å®çŸ©ãutils.lua
ããŸãã function table.random(t) return t[love.math.random(1, #t)] end
ã芧ã®ãšããã圌女ã¯ããŒãã«ããã©ã³ãã ãªã¢ã€ãã ãéžæããã ãã§ãããã®å Žåã-1ãŸãã¯1ãéžæããã ãã§ããªããžã§ã¯ããäœæããåŽã瀺ããŸããå€-1ãéžæãããŠããå Žåããªããžã§ã¯ãã¯ç»é¢ã®å·ŠåŽã«äœæããã1ã®å Žåã¯å³åŽã«äœæãããŸãããã®éžæãããäœçœ®ã®ç¹å®ã®äœçœ®ã¯-48
ãŸãã¯gw+48
ã«çãããªããŸããã€ãŸãããªããžã§ã¯ãã¯ç»é¢ã®å€åŽã«äœæãããŸããããã®ç«¯ã«ååè¿ããªããŸããæ¬¡ã«ãé床ã®ããã€ãã®éããé€ããŠã匟è¬ãšã»ãŒåãæ¹æ³ã§ãªããžã§ã¯ããå®çŸ©ããŸãããªããžã§ã¯ããå³åŽã«äœæãããå Žåã¯ãå·ŠåŽã«ç§»åããå·ŠåŽã«ããå Žåã¯å³åŽã«ç§»åããå¿
èŠããããŸãããããã£ãŠãé床ã«ã¯20ã40ã®ã©ã³ãã ãªå€ãå²ãåœãŠãããæ¬¡ã«ãä¹ç®ãã-direction
ãŸããããã¯ããªããžã§ã¯ããå³åŽã«ããå Žåãdirection
1ã«çãã;å·ŠåŽã«ç§»åãããã®ã§ãé床ã¯è² ã«ãªããŸãïŒå察åŽã®å Žåã¯ãã®éïŒã xè»žã«æ²¿ã£ããªããžã§ã¯ãã®é床ã®ã³ã³ããŒãã³ãã«ã¯åžžã«å±æ§å€ãå²ãåœãŠãããv
y è»žã«æ²¿ã£ãã³ã³ããŒãã³ãã¯0ã«èšå®ãããŸãããªããžã§ã¯ããæ°Žå¹³ç·ã«æ²¿ã£ãŠç§»åãããããyã«æ²¿ã£ãé床ã0ã«èšå®ããŸããæåŸã®äž»ãªéãã¯æç»æ¹æ³ã§ãã function Boost:draw() love.graphics.setColor(boost_color) pushRotate(self.x, self.y, self.collider:getAngle()) draft:rhombus(self.x, self.y, 1.5*self.w, 1.5*self.h, 'line') draft:rhombus(self.x, self.y, 0.5*self.w, 0.5*self.h, 'fill') love.graphics.pop() love.graphics.setColor(default_color) end
åäžã®è±åœ¢ãæç»ãã代ããã«ãå
éšãšå€éšã1ã€ãã€æç»ããŸããããã¯äžçš®ã®ã¢ãŠãã©ã€ã³ã«ãªããŸãããã¡ããã奜ããªããã«ãªããžã§ã¯ããæç»ã§ããŸãããç§ã¯ãã®æ¹æ³ãå人çã«éžæããŸãããããã§ã¯ããšãã§ã¯ãã«ç§»ããŸããããããã§ã¯2ã€ã®ãªããžã§ã¯ãã䜿çšãããŸãã1ã€ã¯AmmoEffect
ïŒãã ããããå°ãè€éã§ãïŒã«äŒŒãŠããŸãã2ã€ç®ã¯textã«äœ¿çšãããŸã+BOOST
ã AmmoEffectã«äŒŒããã®ããå§ããŠãååãä»ãBoostEffect
ãŸãããã®å¹æã¯2ã€ã®éšåã§æ§æãããŠããŸããçœããã©ãã·ã¥ã®ããäžå€®ãšãæ¶ããåŸã®ããªãã«ãŒå¹æã§ããã»ã³ã¿ãŒã¯åãããAmmoEffect
ã«æ©èœããŸãããå¯äžã®éãã¯åãã§ãŒãºã®å®è¡æéã§ããæåã®ãã§ãŒãºã§ã¯0.1ã0.2ã2çªç®ã®ãã§ãŒãºã§ã¯0.15ã0.35ã§ãã function BoostEffect:new(...) ... self.current_color = default_color self.timer:after(0.2, function() self.current_color = self.color self.timer:after(0.35, function() self.dead = true end) end) end
广ã®2çªç®ã®éšåã¯ãåœŒã®æ»ã®åã®ã¡ãã€ãã§ããããªãã«ãŒã¯ã倿°ãäœæããããšã§å®çŸã§ããŸãvisible
ãtrueã®å Žåã广ãæç»ãããfalseã®å Žåãæç»ãããŸããããã®å€æ°ã®å€ã倿Žããããšã«ãããç®çã®å¹æãåŸãããŸãã function BoostEffect:new(...) ... self.visible = true self.timer:after(0.2, function() self.timer:every(0.05, function() self.visible = not self.visible end, 6) self.timer:after(0.35, function() self.visible = true end) end) end
ããã§ã¯ãå¯èŠæ§ãšéå¯èŠæ§ãåãæ¿ããããã«ãevery
0.05ç§ã®ééã§6ååŒã³åºãã䜿çšããå®äºåŸãæåŸã«ãšãã§ã¯ãã衚瀺ããŸãããšãã§ã¯ãã¯0.55ç§åŸã«ãæ»ã¬ãããïŒdead
çŸåšã®è²ãèšå®ãããšãã«0.55åŸã«å€ãtrueã«èšå®ããããïŒãæåŸã«èŠããããã«ããããšã¯ããã»ã©éèŠã§ã¯ãããŸãããããã§ã次ã®ããã«æç»ã§ããŸãã function BoostEffect:draw() if not self.visible then return end love.graphics.setColor(self.current_color) draft:rhombus(self.x, self.y, 1.34*self.w, 1.34*self.h, 'fill') draft:rhombus(self.x, self.y, 2*self.w, 2*self.h, 'line') love.graphics.setColor(default_color) end
åçŽã«ç°ãªããµã€ãºã®å
åŽãšå€åŽã®ã²ã圢ãæç»ããŸããç¹å®ã®å€ïŒ1.34ã2ïŒã¯ãäž»ã«è©Šè¡é¯èª€ã«ãã£ãŠå°ãåºãããŸãããã®å¹æã®ããã«æåŸã«è¡ãå¿
èŠãããã®ã¯ããªããžã§ã¯ãã®åç¶æéäžã«å€éšã®ã¢ãŠãã©ã€ã³è±åœ¢ãå¢ããããšã§ããæ¬¡ã®ããã«ã§ããŸãã function BoostEffect:new(...) ... self.sx, self.sy = 1, 1 self.timer:tween(0.35, self, {sx = 2, sy = 2}, 'in-out-cubic') end
次ã«ãæç»é¢æ°ã次ã®ããã«å€æŽããŸãã function BoostEffect:draw() ... draft:rhombus(self.x, self.y, self.sx*2*self.w, self.sy*2*self.h, 'line') ... end
ãã®å€æ°ã®ãããã§sx
ãšsy
0.35ç§ã®äºéã®ããã«ãããŸãã«ãã0.35ã§ããç§ãåè·¯çšã®2ã«å¢å ãããŸããæçµçã«ãçµæã¯æ¬¡ã®ããã«ãªããŸãïŒdie
匟è¬ãªãœãŒã¹ã§è¡ã£ãããã«ããã®ãªããžã§ã¯ãã®æ©èœãPlayerã®è¡çªã€ãã³ãã«æ¢ã«ãªã³ã¯ããŠãããšä»®å®ããŸãïŒã
ããã§ã¯ããšãã§ã¯ãã®ä»ã®éšåãã¯ã¬ã€ãžãŒããã¹ãã«ã€ããŠèŠãŠã¿ãŸãããããã®ããã¹ã广ã¯ã²ãŒã ã®ã»ãŒãã¹ãŠã®å Žæã§äœ¿çšããããããæ£ããå®è£
ããå¿
èŠããããŸããããäžåºŠãã©ã®ããã«èŠãããã瀺ããŸãããŸãããšãã§ã¯ããããã€ãã®éšåã«åããŸããããæåã«æ°ä»ãã®ã¯ãç»é¢ã«æåã«æãããç·ã ãã§ãããæåŸã«åãã£ãŠãªããžã§ã¯ãã®ããã«ã¡ãã€ãå§ããŸãBoostEffect
ã Flickerã¯BoostEffectãšåãããžãã¯ã䜿çšããŸããã€ãŸããæ¢ã«èª¿ã¹ãŸããããŸããæååã®æåã¯ä»ã®æåã«ã©ã³ãã ã«å€åãå§ããåæåã®èæ¯ãã©ã³ãã ã«è²ãå€åããŸããããã¯ããã®ãšãã§ã¯ããåãã£ã©ã¯ã¿ãŒãåå¥ã«åŠçããè¡å
šäœã§åäœããªãããšã瀺ããŠããŸããã€ãŸãããã¹ãŠã®ãã£ã©ã¯ã¿ãŒãããŒãã«ã«ä¿åããcharacters
ãã®ããŒãã«ãåŠçããŠããããã¹ãŠã®å€æŽãšãšãã§ã¯ãã䜿çšããŠç»é¢äžã®ããŒãã«ããåãã£ã©ã¯ã¿ãŒãæç»ããå¿
èŠããããŸããããããã¹ãŠãèæ
®ããŠãclassã®åºåºã決å®ã§ãInfoText
ãŸããæ¬¡ã®ããã«åŒã³åºããŸãã function Boost:die() ... self.area:addGameObject('InfoText', self.x, self.y, {text = '+BOOST', color = boost_color}) end
ã€ãŸããæååã¯å±æ§ã«ä¿åãããŸãtext
ããã®å Žåãã¯ã©ã¹ã®åºåºã®å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã function InfoText:new(...) ... self.depth = 80 self.characters = {} for i = 1, #self.text do table.insert(self.characters, self.text:utf8sub(i, i)) end end
ãã®ããããªããžã§ã¯ãã®æ·±ãã¯80ïŒä»ã®ãã¹ãŠã®ãªããžã§ã¯ããããé«ããã€ãŸããã¹ãŠã®äžã«æç»ãããïŒã§ãããšå€æããå
ã®æååãããŒãã«æåã«åå²ããŸãããã®ããã«ãã©ã€ãã©ãªã䜿çšããŸãutf8
ãäžè¬ã«ããã¹ãŠã®çš®é¡ã®æåããµããŒãããã©ã€ãã©ãªã䜿çšããŠæååãæäœããããšããå§ãããŸããããã¯ãåŸã§èª¬æããããã«ããªããžã§ã¯ãã«ãšã£ãŠç¹ã«éèŠã§ãããŸãããããã®ãã£ã©ã¯ã¿ãŒã®ã¬ã³ããªã³ã°ãåå¥ã«è¡ãå¿
èŠããããŸããããã¯ãåè¿°ã®ãšãããåãã£ã©ã¯ã¿ãŒã«ã¯ç¬èªã®èæ¯ããããã©ã³ãã ã«å€åããããã§ããåæåãåå¥ã«ã¬ã³ããªã³ã°ããããžãã¯ã¯ãæåããŒãã«ã調ã¹ãŠãäœçœ®xã«åæåãæç»ããããšã§ããäœçœ®xã¯ããã®åã«ãããã¹ãŠã®æåã®åèšã§ããã€ãŸããããšãã°ãæåã®O
è¡å
+BOOST
ã¯äœçœ®ã§ã®ã¬ã³ããªã³ã°ãæå³ããŸãinitial_x_position + widthOf('+B')
ããã®å Žåãå¹
ãååŸããéã®åé¡+B
ã¯ã颿°ã䜿çšããããFont:getWidth
ãŸã ãã©ã³ããèšå®ããŠããªãããã䜿çšãããã©ã³ãã«äŸåããããšã§ãããã ãããã®åé¡ã¯ç°¡åã«è§£æ±ºã§ããŸãïŒãã®ããã«ãç§ãã¡ã¯ããã©ã³ãã䜿çšm5x7ãããšã«Linssenãããã®ãã©ã³ãããã©ã«ããŒã«å
¥ããŠresources/fonts
ããããŠã³ããŒãã§ããŸãããã©ã«ããŒããã¯ã©ã¹å®çŸ©ãããŒãããããã«äœ¿çšãããã³ãŒãobjects
ïŒæŒç¿14ïŒã«äŒŒãŠãããããããŠã³ããŒãã«å¿
èŠãªã³ãŒãã¯æŒç¿ãšããŠæ®ããŠãããŸãããã®ããŠã³ããŒãããã»ã¹ã®çµäºãŸã§ã«ãããŠã³ããŒãããfonts
ãã¹ãŠã®ãã©ã³ããæ¬¡ã®åœ¢åŒã§å«ãã°ããŒãã«ããŒãã«ãäœæãããŸããfontname_fontsize
ããã®äŸã§ã¯ã次ã䜿çšããŸãm5x7_16
ã function InfoText:new(...) ... self.font = fonts.m5x7_16 ... end
ãããŠãã¬ã³ããªã³ã°ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã function InfoText:draw() love.graphics.setFont(self.font) for i = 1, #self.characters do local width = 0 if i > 1 then for j = 1, i-1 do width = width + self.font:getWidth(self.characters[j]) end end love.graphics.setColor(self.color) love.graphics.print(self.characters[i], self.x + width, self.y, 0, 1, 1, 0, self.font:getHeight()/2) end love.graphics.setColor(default_color) end
ãŸããããlove.graphics.setFont
ã䜿çšããŠã次ã®ã¬ã³ããªã³ã°æäœã§äœ¿çšãããã©ã³ããæå®ããŸããæ¬¡ã«ãåã·ã³ãã«ã調ã¹ãŠãããããæç»ããå¿
èŠããããŸããããããæåã«ãxã§äœçœ®ãèšç®ããå¿
èŠããããŸããããã¯ããã®åã®ãã¹ãŠã®æåã®å¹
ã®åèšã§ãã倿°ãèç©ããå
åŽã®ã«ãŒãwidth
ã¯ãŸãã«ãããè¡ããŸãã 1ïŒè¡ã®å
é ïŒããi-1ïŒçŸåšã®è¡ã®åã®æåïŒã§å§ãŸããåæåã®å¹
ãtotal width
ãã€ãŸããã¹ãŠã®åèšã«å ç®ããŸããæ¬¡ã«ãlove.graphics.print
ããããã®ãã£ã©ã¯ã¿ãŒã察å¿ããäœçœ®ã«æç»ããŸãããŸããåæåããã©ã³ãã®é«ãã®ååã ãã·ããããŸãïŒãããã£ãŠãèšå®ããyäœçœ®ã«å¯ŸããŠæåãäžå€®ã«é
眮ãããŸãïŒãããããã¹ãŠããã¹ããããšã次ã®çµæãåŸãããŸãããŸãã«å¿
èŠãªãã®ïŒããã§ãæ¶ããåã«ç¹æ»
ããããã¹ãã«é²ãããšãã§ããŸãããã®å¹æã¯ãBoostEffectãªããžã§ã¯ããšåãããžãã¯ã䜿çšããŸããã€ãŸããåçŽã«ã³ããŒã§ããŸãã function InfoText:new(...) ... self.visible = true self.timer:after(0.70, function() self.timer:every(0.05, function() self.visible = not self.visible end, 6) self.timer:after(0.35, function() self.visible = true end) end) self.timer:after(1.10, function() self.dead = true end) end
ãããå®è¡ãããšãããã¹ãããã°ããã®éæ£åžžã®ãŸãŸã§ãããã¡ãã€ãå§ããŠæ¶ããããšãããããŸãããããŠä»ãæãé£ããã®ã¯ãåãã£ã©ã¯ã¿ãŒãã©ã³ãã ã«å€æŽããããšã§ããã¡ã€ã³ãšèæ¯ã®è²ã«ã€ããŠãåãããšãè¡ããŸãããããã®å€æŽã¯ãã·ã³ãã«ãã¡ãã€ãå§ããã®ãšã»ãŒåæã«éå§ããããããafter
äžèšã§å®çŸ©ãã0.7ç§éãã³ãŒãã®ãã®éšåãåŒã³åºãå
ã«é
眮ããŸãããããè¡ããŸã-0.035ç§ããšã«ããã£ã©ã¯ã¿ãŒãå¥ã®ã©ã³ãã ãªãã£ã©ã¯ã¿ãŒã«å€æŽããæ©äŒã®ããæé ãéå§ããŸããæ¬¡ã®ããã«ãªããŸãã self.timer:after(0.70, function() ... self.timer:every(0.035, function() for i, character in ipairs(self.characters) do if love.math.random(1, 20) <= 1 then
ã€ãŸãã0.035ç§ããšã«ãåãã£ã©ã¯ã¿ãŒã¯äœãä»ã®ãã®ã«å€ãã確çã5ïŒ
ã§ãããããçµäºããã«ã¯ã倿°ã远å ããŸãrandom_characters
ãããã¯ãæåã倿Žã§ãããã¹ãŠã®æåãå«ãæååã§ãããã£ã©ã¯ã¿ãŒã倿Žããå¿
èŠãããå Žåããã®è¡ããã©ã³ãã ã«ãã£ã©ã¯ã¿ãŒãéžæããŸãã self.timer:after(0.70, function() ... self.timer:every(0.035, function() local random_characters = '0123456789!@#$%š&*()-=+[]^~/;?><.,|abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYXZ' for i, character in ipairs(self.characters) do if love.math.random(1, 20) <= 1 then local r = love.math.random(1, #random_characters) self.characters[i] = random_characters:utf8sub(r, r) else self.characters[i] = character end end end) end)
ã³ãŒããå®è¡ãããšã次ã®ããã«ãªããŸããåãããžãã¯ã䜿çšããŠãã·ã³ãã«ã®åæ¯è²ãšèæ¯è²ã倿Žã§ããŸãããããè¡ãããã«ãæã
ã¯2ã€ã®ããŒãã«ãå®çŸ©ããbackground_colors
ãããŠforeground_colors
ãåããŒãã«ã®ãµã€ãºã¯tableãšåãã§characters
ãåæåã®èæ¯è²ãšåæ¯è²ã®ã¿ãå«ãŸããŸããäžéšã®ãã£ã©ã¯ã¿ãŒã§ãã®è¡šã®è²ãæå®ãããŠããªãå Žåãããã©ã«ãã§ã¯ã¡ã€ã³ã®è²ïŒboost_color
ïŒãšéæãªèæ¯ã䜿çšãããŸãã function InfoText:new(...) ... self.background_colors = {} self.foreground_colors = {} end function InfoText:draw() ... for i = 1, #self.characters do ... if self.background_colors[i] then love.graphics.setColor(self.background_colors[i]) love.graphics.rectangle('fill', self.x + width, self.y - self.font:getHeight()/2, self.font:getWidth(self.characters[i]), self.font:getHeight()) end love.graphics.setColor(self.foreground_colors[i] or self.color or default_color) love.graphics.print(self.characters[i], self.x + width, self.y, 0, 1, 1, 0, self.font:getHeight()/2) end end
å®çŸ©ãããŠããå Žåbackground_colors[i]
ïŒçŸåšã®æåã®èæ¯è²ïŒãèæ¯è²ã«ã€ããŠã¯ãçŸåšã®æåã®é©åãªäœçœ®ãšãµã€ãºã«é·æ¹åœ¢ãæç»ããã ãã§ããã䜿çšãsetColor
ãŠçŸåšã®ã·ã³ãã«ã®ã¬ã³ããªã³ã°è²ãèšå®ããã ãã§ãåè²ã倿ŽããŸããforeground_colors[i]
å®çŸ©ãããŠããªãå Žåãããã©ã«ãã§ã¯equal self.color
ã«ãªããŸããããã¯boost_color
ãBoostãªããžã§ã¯ãããåŒã³åºããããšãã«æ£ç¢ºã«è»¢éãããããããã®ãªããžã§ã¯ãã§ã¯åžžã«equal ã§ãããã ããself.color
å®çŸ©ãããŠããªãå Žåã¯ãããã©ã«ãã§çœïŒdefault_color
ïŒã«ãªããŸããããŒãã«background_colors
ãšã®äžã«å€ãå®çŸ©ããŠããªãããããã®ã³ãŒãèªäœã¯äœãããŸããforeground_colors
ããããè¡ãã«ã¯ãæåãã©ã³ãã ã«å€æŽããããã«äœ¿çšããã®ãšåãããžãã¯ã䜿çšã§ããŸãã self.timer:after(0.70, function() ... self.timer:every(0.035, function() for i, character in ipairs(self.characters) do ... if love.math.random(1, 10) <= 1 then
è²ã眮ãæããã³ãŒãã¯ãè²ã®ãªã¹ãããéžæããå¿
èŠããããŸãã6è²ã®ã°ããŒãã«ã°ã«ãŒããå®çŸ©ããã®ã§ãããããã¹ãŠããªã¹ãã«å
¥ããŠãããã䜿çšããŠãã®ãã¡ã®1ã€ãã©ã³ãã ã«éžæã§ããŸãtable.random
ãããã«ãããã«å ããŠã6ã€ã®ãœãŒã¹ã®ãã¬ãšãªã6è²ãããã«å®çŸ©ããŸããã€ãŸããå
ã®è²ããã232, 48, 192
å Žåããã®ãã¬ã¯ãšããŠå®çŸ©ã§ããŸã255-232, 255-48, 255-192
ã function InfoText:new(...) ... local default_colors = {default_color, hp_color, ammo_color, boost_color, skill_point_color} local negative_colors = { {255-default_color[1], 255-default_color[2], 255-default_color[3]}, {255-hp_color[1], 255-hp_color[2], 255-hp_color[3]}, {255-ammo_color[1], 255-ammo_color[2], 255-ammo_color[3]}, {255-boost_color[1], 255-boost_color[2], 255-boost_color[3]}, {255-skill_point_color[1], 255-skill_point_color[2], 255-skill_point_color[3]} } self.all_colors = fn.append(default_colors, negative_colors) ... end
ããã§ã¯ãåè²ã®å¯Ÿå¿ããå€ãå«ã2ã€ã®ããŒãã«ãå®çŸ©ãã颿°append
ã䜿çšããŠããããçµåããŸããæ¬¡ã«ããã®ãããªããšãããŠtable.random(self.all_colors)
ããã®è¡šã§å®çŸ©ãããŠãã10åããã©ã³ãã ãªè²ã1ã€ååŸããŸããã€ãŸããæ¬¡ã®ããšãã§ããŸãã self.timer:after(0.70, function() ... self.timer:every(0.035, function() for i, character in ipairs(self.characters) do ... if love.math.random(1, 10) <= 1 then self.background_colors[i] = table.random(self.all_colors) else self.background_colors[i] = nil end if love.math.random(1, 10) <= 2 then self.foreground_colors[i] = table.random(self.all_colors) else self.background_colors[i] = nil end end end) end)
ã²ãŒã ãå®è¡ãããšã次ã®ããã«è¡šç€ºãããŸãã以äžã§ãã
åŸã§ãã®å¹æãæ¹åããŸãïŒæŒç¿ãå«ãïŒããä»ã®ãšããããã§ååã§ããæåŸã«è¡ãå¿
èŠãããã®ã¯ãå éãªãœãŒã¹ãåéãããšãã«ãã¬ã€ã€ãŒã«+25ã®ããŒã¹ãã远å ããããšã§ããããã¯åŒŸè¬ãªãœãŒã¹ãšãŸã£ããåãããã«æ©èœãããããã³ãŒãã¯ã¹ãããããŸãããªãœãŒã¹æŒç¿
95. Projectileè¡çªã¯ã©ã¹ãPlayerè¡çªã¯ã©ã¹ãç¡èŠããããã«ããŸãã96.颿°ã倿ŽããŠaddAmmo
ãè² ã®å€ã®è¿œå ããµããŒããã屿§ammo
ã0ãäžåããªãããã«ããŸãã颿°addBoost
ããã³addHP
HPãªãœãŒã¹ã®è¿œå ãåæ§ã«è¡ããŸãïŒå¥ã®æŒç¿ã®ã¿ã¹ã¯ã«ãªããŸãïŒã97.åã®æŒç¿ãã倿ãããšãæ£ã®å€ãšè² ã®å€ã1ã€ã®é¢æ°ã§åŠçãããã颿°addResource
ãšé¢æ°ã«åå²ããæ¹ãããremoveResource
ã§ããããïŒ98.ãªããžã§ã¯ãInfoText
ã§ãã·ã³ãã«ã20ïŒ
å€åãã確çãã¡ã€ã³ã«ã©ãŒã5ïŒ
å€åãã確çãããã³èæ¯è²ã30ïŒ
å€åãã確çã倿ŽããŸãã99.ããŒãã«ãå®çŸ©ããdefault_colors
ãnegative_colors
ãããŠall_colors
ã«ãããInfoText
éããŒã«ã«ããã³ã°ããŒãã«ã100ã¯ããªããžã§ã¯ãã®äœçœ®ãã©ã³ãã åãInfoText
ããããéã«äœæãããããã«-self.w
ããself.w
æåxã®ãé-self.h
ããã³self.h
æåYã«ã屿§w
ãšã¯ãh
察象ããŒã¹ããããæ
å ±ããã¹ããäœæããŸããã101.æ¬¡ã®æ©èœããããšããŸãã function Area:getAllGameObjectsThat(filter) local out = {} for _, game_object in pairs(self.game_objects) do if filter(game_object) then table.insert(out, game_object) end end return out end
ãã£ã«ã¿ãŒé¢æ°ãæž¡ãAreaå
ã®ãã¹ãŠã®ã²ãŒã ãªããžã§ã¯ããè¿ããŸãããŸããInfoTextã³ã³ã¹ãã©ã¯ã¿ãŒã§æ¬¡ã®ããã«åŒã³åºããããšããŸãã function InfoText:new(...) ... local all_info_texts = self.area:getAllGameObjectsThat(function(o) if o:is(InfoText) and o.id ~= self.id then return true end end) end
ããã¯ãçŸåšã§ã¯ãªããã¹ãŠã®æ¢åããã³çŸåšã®InfoTextãªããžã§ã¯ããè¿ããŸãã InfoTextãªããžã§ã¯ããä»ã®InfoTextãªããžã§ã¯ããšèŠèŠçã«éè€ããªãããã«ããŠãã ãããã€ãŸããç»é¢äžã®åãã¹ããŒã¹ãå æãããããã¹ããèªããªããªãããšã¯ãããŸãããããã¯ããªãã«ãšã£ãŠéœåã®è¯ãæ¹æ³ã§è¡ãããšãã§ããŸããäž»ãªããšã¯ãã¿ã¹ã¯ãå®è¡ããããšã§ãã102.ïŒã³ã³ãã³ãïŒãã¹ãŠã®æ©èœãšèŠèŠå¹æãåããHPãªãœãŒã¹ã远å ããŸãã BoostãªãœãŒã¹ãšãŸã£ããåãããžãã¯ã䜿çšããŸããã+ 25 HPã远å ããŸãããªãœãŒã¹ãšå¹æã¯æ¬¡ã®ããã«ãªããŸãã103.ïŒã³ã³ãã³ãïŒãã¹ãŠã®æ©èœãšèŠèŠå¹æãåããSPãªãœãŒã¹ã远å ããŸãããªãœãŒã¹ãšåãããžãã¯ã䜿çšããŸããã+ 1 SPã远å ããŸããããã«ãSPãªãœãŒã¹ã¯ãPlayerãªããžã§ã¯ãã®å
éšå€æ°ãšããŠã§ã¯ãªããã°ããŒãã«å€æ°ãšããŠå®çŸ©ããå¿
èŠããããŸãããªãœãŒã¹ãšå¹æã¯æ¬¡ã®ããã«ãªããŸããæ»æ
ããŠãæ»æã«ç§»ããŸãããããŸããã·ã§ã«ã®ã¬ã³ããªã³ã°æ¹æ³ã倿ŽããŸããä»ã§ã¯ãããã¯åãšããŠæãããŠããŸãããããããç·ã«ãããã®ã§ããããã¯æ¬¡ã®ããã«å®è£
ã§ããŸãã function Projectile:draw() love.graphics.setColor(default_color) pushRotate(self.x, self.y, Vector(self.collider:getLinearVelocity()):angle()) love.graphics.setLineWidth(self.s - self.s/4) love.graphics.line(self.x - 2*self.s, self.y, self.x, self.y) love.graphics.line(self.x, self.y, self.x + 2*self.s, self.y) love.graphics.setLineWidth(1) love.graphics.pop() end
ãã®é¢æ°ã§pushRotate
ã¯ãçºå°äœã®é床ã䜿çšãããããçºå°äœãåãè§åºŠã«å¿ããŠçºå°äœãå転ãããããšãã§ããŸããæ¬¡ã«ãå
éšã§love.graphics.setLineWidth
ã屿§ã«ã»ãŒæ¯äŸããå€ã䜿çšããŠèšå®ããŸããs
ããããããããã«å°ããããŸããããã¯ãs
å
šäœã倧ããã·ã§ã«ãåããªãããšãæå³ããŸããæ¬¡ã«ãã§ã·ã§ã«ãæç»ããŸãlove.graphics.line
ããŸã-2*self.s
ãäžå¿ãã1æ¬ã®ç·ãåŒããæ¬¡ã«äžå¿ããã«å¥ã®ç·ãåŒãããšãéèŠã§ã2*self.s
ãåæ»æã«ã¯ç¬èªã®è²ãããããããã®ç·ã®1ã€ã®è²ã倿ŽããŸããã2çªç®ã®ç·ã®è²ã¯å€æŽããªãããããããè¡ããŸããããšãã°ããããè¡ãå ŽåïŒ function Projectile:draw() love.graphics.setColor(default_color) pushRotate(self.x, self.y, Vector(self.collider:getLinearVelocity()):angle()) love.graphics.setLineWidth(self.s - self.s/4) love.graphics.line(self.x - 2*self.s, self.y, self.x, self.y) love.graphics.setColor(hp_color)
次ã«ããã®ããã«ãªããŸãïŒãããã£ãŠãåæ»æã«ç°ãªãè²ãå²ãåœãŠããã¬ã€ã€ãŒãç»é¢äžã§äœãèµ·ãã£ãŠããããããããçè§£ã§ããããã«ããããšãã§ããŸãã
宿ããã²ãŒã ã«ã¯16ã®æ»æããããŸãããããã§ã¯ãã®ãã¡ã®äžéšã®ã¿ãæ€èšããŸããæ»æã·ã¹ãã ã¯éåžžã«ã·ã³ãã«ã§ã次ã®ã«ãŒã«ã«åºã¥ããŠããŸãã- æ»æïŒäžç«ãé€ãïŒã¯ãåã·ã§ããã§åŒŸè¬ãæ¶è²»ããŸãã
- 匟è¬ã0ã«ãªããšãçŸåšã®æ»æã¯äžç«ã«å€ãããŸãã
- ã©ã³ãã ã«çæããããªãœãŒã¹ã䜿çšããŠãæ°ããæ»æãååŸã§ããŸãã
- æ°ããæ»æãåä¿¡ããããšãçŸåšã®æ»æã眮ãæãããã匟è¬ãå®å
šã«åŸ©å
ãããŸãã
- åæ»æã¯ç¬èªã®éã®åŒŸè¬ã䜿çšããç¬èªã®ç¹æ§ãæã£ãŠããŸãã
æåã«è¡ãããšã¯ãåæ»æã«ã€ããŠã®æ
å ±ãå«ãããŒãã«ãå®çŸ©ããããšã§ãïŒãããã®ãå·åŽãã®æéã匟è¬ãšè²ã®æ¶è²»ãããŒãã«ãå®çŸ©ããŸããglobals.lua
ãä»ã®ãšããã¯æ¬¡ã®ããã«ãªããŸãã attacks = { ['Neutral'] = {cooldown = 0.24, ammo = 0, abbreviation = 'N', color = default_color}, }
å®çŸ©æžã¿ã®æšæºçãªæ»æã¯ãšåŒã°ãNeutral
ãŸãã圌女ã¯ãã²ãŒã ã§æ¢ã«æã£ãŠããæ»æã®ãã©ã¡ãŒã¿ãŒã䜿çšããŸããããã§setAttack
ãããæ»æãå¥ã®æ»æã«çœ®ãæãã颿°ãå®çŸ©ããæ¬¡ã®æ»æã®ã°ããŒãã«ããŒãã«ã䜿çšã§ããŸãã function Player:setAttack(attack) self.attack = attack self.shoot_cooldown = attacks[attack].cooldown self.ammo = self.max_ammo end
次ã®ããã«åŒã³åºãããšãã§ããŸãã function Player:new(...) ... self:setAttack('Neutral') ... end
ããã§ã¯attack
ãçŸåšã®æ»æã®ååãå«ã屿§ã倿Žããã ãã§ãããã®å±æ§ã¯shoot
ãçŸåšã¢ã¯ãã£ããªæ»æã確èªããã·ã§ã«ãäœæããæ¹æ³ã決å®ããããã«ã颿°ã§äœ¿çšãããŸãã屿§ã倿Žããããšãã§ããŸãshoot_cooldown
ããã®å±æ§ã¯ãŸã äœæããŠããŸããããboost_timer
and 屿§ã«äŒŒãŠããŸãboost_cooldown
ãããã¯ãã¢ã¯ã·ã§ã³ïŒãã®å Žåã¯æ»æïŒãçºçããé »åºŠãå¶åŸ¡ããããã«äœ¿çšãããŸãããã®è¡ãåé€ããŸãã function Player:new(...) ... self.timer:every(0.24, function() self:shoot() end) ... end
ãããŠãæ»æã®ã¿ã€ãã³ã°ãæåã§èšå®ããŸãã function Player:new(...) ... self.shoot_timer = 0 self.shoot_cooldown = 0.24 ... end function Player:update(dt) ... self.shoot_timer = self.shoot_timer + dt if self.shoot_timer > self.shoot_cooldown then self.shoot_timer = 0 self:shoot() end ... end
æ©èœã®æåŸã«ã匟è¬ã®éã埩å
ããŸããããã§ãã«ãŒã«4ãå®è£
ããŸããæ¬¡ã«ã§ããããšã¯shoot
ãããŸããŸãªæ»æã®ååšãèæ
®ã«å
¥ããããã«é¢æ°ãå°ã倿Žããããšã§ãã function Player:shoot() local d = 1.2*self.w self.area:addGameObject('ShootEffect', self.x + d*math.cos(self.r), self.y + d*math.sin(self.r), {player = self, d = d}) if self.attack == 'Neutral' then self.area:addGameObject('Projectile', self.x + 1.5*d*math.cos(self.r), self.y + 1.5*d*math.sin(self.r), {r = self.r}) end end
çºå°ç©ãçºå°ããåã«ãæ¡ä»¶ä»ãèšèšã䜿çšããŠif self.attack == 'Neutral'
çŸåšã®æ»æã確èªããŸãã16åã®æ»æãã¹ãŠããã§ãã¯ããå¿
èŠãããããããã®æ©èœã¯åŸã
ã«å€§ããªæ¡ä»¶ãã§ãŒã³ã«æé·ããŸãã
1ã€ã®æ»æã远å ããŠãã©ã®ããã«èŠããããèŠãŠã¿ãŸãããã远å ããæ»æã¯ãšåŒã°ãDouble
ãŸããæ¬¡ã®ããã«ãªããŸããã芧ã®ãšããã圌女ã¯1ã€ã§ã¯ãªã2ã€ã®ã·ã§ã«ã§æãã«æã¡ãŸããæåã«ãæ»æã®èª¬æãã°ããŒãã«æ»æããŒãã«ã«è¿œå ããå¿
èŠããããŸãããã®æ»æã®å·åŽæéã¯0.32ç§ã§ã匟è¬2åãæ¶è²»ãããã®è²ã¯æ¬¡ã®ããã«ãªããŸãammo_color
ïŒãããã®å€ã¯è©Šè¡é¯èª€ã§ååŸããŸããïŒã attacks = { ... ['Double'] = {cooldown = 0.32, ammo = 2, abbreviation = '2', color = ammo_color}, }
ããã颿°ã«è¿œå ã§ããŸãshoot
ïŒ function Player:shoot() ... elseif self.attack == 'Double' then self.ammo = self.ammo - attacks[self.attack].ammo self.area:addGameObject('Projectile', self.x + 1.5*d*math.cos(self.r + math.pi/12), self.y + 1.5*d*math.sin(self.r + math.pi/12), {r = self.r + math.pi/12, attack = self.attack}) self.area:addGameObject('Projectile', self.x + 1.5*d*math.cos(self.r - math.pi/12), self.y + 1.5*d*math.sin(self.r - math.pi/12), {r = self.r - math.pi/12, attack = self.attack}) end end
ããã§ã¯ã1ã€ã§ã¯ãªã2ã€ã®ã·ã§ã«ãäœæããŠããŸããããããã®ã·ã§ã«ã¯ãmath.pi / 12ã©ãžã¢ã³ãŸãã¯15床ã®è§åºŠã«åããããŠããŸãããŸããã·ã§ã«ã«æ»æã®ååãšããŠå±æ§ãååŸãããŸããattack
ãçºå°ç©ãã©ã®ã¿ã€ãã®æ»æã«å±ããŠãããã倿ããã®ã«åœ¹ç«ã€ãããçºå°ç©ã®ã¿ã€ãããšã«ãããè¡ããŸããããã¯ãé©åãªè²ãèšå®ããããå¿
èŠã«å¿ããŠåäœã倿Žãããããã®ã«åœ¹ç«ã¡ãŸããProjectileãªããžã§ã¯ãã¯æ¬¡ã®ããã«ãªããŸãã function Projectile:new(...) ... self.color = attacks[self.attack].color ... end function Projectile:draw() pushRotate(self.x, self.y, Vector(self.collider:getLinearVelocity()):angle()) love.graphics.setLineWidth(self.s - self.s/4) love.graphics.setColor(self.color) love.graphics.line(self.x - 2*self.s, self.y, self.x, self.y) love.graphics.setColor(default_color) love.graphics.line(self.x, self.y, self.x + 2*self.s, self.y) love.graphics.setLineWidth(1) love.graphics.pop() end
ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯color
ããã®æ»æã«å¯ŸããŠã°ããŒãã«ããŒãã«ã§å®çŸ©ãããè²ãèšå®ããŸãattacks
ããããŠãæç»é¢æ°ã§ã¯ã屿§color
ã§ãããã®è²ã§ç·ã®äžéšãæç»ããããäžæ¹ã§ããç·ãæç»ããŸãdefault_color
ãã»ãšãã©ã®ã¿ã€ãã®ã·ã§ã«ã§ã¯ããã¿ãŒã³ã¯åãã§ããæåŸã«å¿ããŠããŸã£ãã®ã¯ããã®æ»æãã«ãŒã«1ã«æºæ ãããããšã§ããã€ãŸããé©åãªéã®åŒŸè¬ãæ¶è²»ãããã³ãŒãã远å ããã®ãå¿ããŸãããããã¯ããªãç°¡åã«ä¿®æ£ã§ããŸãã function Player:shoot() ... elseif self.attack == 'Double' then self.ammo = self.ammo - attacks[self.attack].ammo ... end end
ããã«ãããã«ãŒã«1ãå®è¡ãããŸãïŒããã«æ»æã®å ŽåïŒãã«ãŒã«2ãå®è£
ããã³ãŒãã远å ããããšãã§ããŸãammo
ã0 ã«ãªã£ãããçŸåšã®æ»æãNeutral
次ã®ããã«å€æŽããŸãã function Player:shoot() ... if self.ammo <= 0 then self:setAttack('Neutral') self.ammo = self.max_ammo end end
shoot
匟è¬ã®éã0ã«ãªã£ãåŸããã¬ãŒã€ãŒã«æãããããªãã®ã§ã颿°ã®æåŸã«ç§»åããå¿
èŠããããŸãããããå®è¡ããŠããã°ã©ã ãå®è¡ããããšãããšã次ã®ããã«ãªããŸããæ»ææŒç¿
104.ïŒCONTENTïŒæ»æãå®è£
ãTriple
ãŸããæ»æããŒãã«ã§ã®å®çŸ©ã¯æ¬¡ã®ãšããã§ãã attacks['Triple'] = {cooldown = 0.32, ammo = 3, abbreviation = '3', color = boost_color}
ãããŠãæ»æèªäœã¯æ¬¡ã®ããã«ãªããŸããã·ã§ã«ã®è§åºŠã¯inãšãŸã£ããåãDouble
ã§ãããäžå€®ã«ïŒæ»æã·ã§ã«ãšåãè§åºŠã§ïŒè¿œå ã®ââã·ã§ã«ãäœæãããŠãNeutral
ãŸããããã«æ»æãšåãæé ã«åŸã£ãŠããã®æ»æãäœæããŸãã105.ïŒCONTENTïŒæ»æãå®è£
ãRapid
ãŸããæ»æããŒãã«ã§ã®å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã attacks['Rapid'] = {cooldown = 0.12, ammo = 1, abbreviation = 'R', color = default_color}
ãããŠãæ»æèªäœã¯æ¬¡ã®ããã«ãªããŸãã106.ïŒCONTENTïŒæ»æãå®è£
ãSpread
ãŸããæ»æã®è¡šã«ããããã®å®çŸ©ïŒ attacks['Spread'] = {cooldown = 0.16, ammo = 1, abbreviation = 'RS', color = default_color}
ãããŠãæ»æèªäœã¯æ¬¡ã®ããã«ãªããŸããã·ã§ããã«äœ¿çšãããè§åºŠã¯ã-math.pi / 8ã+ math.pi / 8ã®ã©ã³ãã ãªå€ã§ãããã®æ»æã®ã·ã§ã«ã®è²ãå°ãç°ãªããŸããè²ã1ã€ã ãã«ããã®ã§ã¯ãªããåãã¬ãŒã ã§è²ããªã¹ãã®1ã€ã«all_colors
ïŒãŸãã¯æ°åã«å¿ããŠãã¬ãŒã å
šäœã§ïŒã©ã³ãã ã«å€æŽããŸãã107.ïŒCONTENTïŒæ»æãå®è£
ãBack
ãŸããæ»æããŒãã«ã§ã®å®çŸ©ã¯æ¬¡ã®ããã«ãªããŸãã attacks['Back'] = {cooldown = 0.32, ammo = 2, abbreviation = 'Ba', color = skill_point_color}
ãããŠãæ»æèªäœã¯æ¬¡ã®ããã«ãªããŸãã108.ïŒCONTENTïŒæ»æãå®è£
ãSide
ãŸããæ»æã®è¡šã«ããããã®å®çŸ©ïŒ attacks['Side'] = {cooldown = 0.32, ammo = 2, abbreviation = 'Si', color = boost_color}
æ»æèªäœïŒ109.ïŒCONTENTïŒãªãœãŒã¹ãå®è£
ãAttack
ãŸãã以äžã®ããBoost
ã§SkillPoint
ãæ»æã®ãªãœãŒã¹ã¯ãç»é¢ã®å·Šç«¯ãŸãã¯å³ç«¯ã«äœæããåŸãéåžžã«ãã£ãããšå
åŽã«ç§»åãããŸãããã¬ãŒã€ãŒãæ»æãªãœãŒã¹ãšå¯Ÿè©±ãããšã颿°ã䜿çšsetAttack
ããæ»æã¯ããªãœãŒã¹ã«å«ãŸããæ»æã«å€ãããŸããAttackãªãœãŒã¹ã¯ãBoostããã³SkillPointãªãœãŒã¹ãšå€èгããããã«ç°ãªããŸããã圌èªèº«ãšåœŒã®å¹æã®åçã¯ã»ãšãã©åãã§ããåãªãœãŒã¹ã«äœ¿çšãããè²ã¯ã·ã§ã«ãšåãã§ãããèå¥ååã¯abbreviation
衚ã§ååãä»ãããã®attacks
ã§ãããããã¯æ¬¡ã®ããã«ãªããŸãããã¬ãŒã€ãŒã«ããæ°ããæ»æãæŸããšãã¯ãInfoTextãªããžã§ã¯ããäœæããããšãå¿ããªãã§ãã ããïŒ
ããŒã8ïŒæµ
ã¯ããã«
ãã®ããŒãã§ã¯ãããã€ãã®æµã®äœæãšãEnemyProjectileã¯ã©ã¹ãã€ãŸããäžéšã®æµããã¬ã€ã€ãŒãæã€ããšãã§ããã·ã§ã«ãæ€èšããŸãããã®éšåã¯ä»ã®éšåãããå°ãçããªããŸããããã¯ããã¹ãŠã®æµã®äœæã«ã€ããŠè©³çްã«èª¬æããã®ã§ã¯ãªãããã¹ãŠã®æµã«ã€ããŠã»ãŒåãã§ããäžè¬çãªåäœã«ã€ããŠã®ã¿èª¬æããããã§ããæµ
ãã®ã²ãŒã ã®æµã¯ãåã®ããŒãã§äœæãããªãœãŒã¹ãšã»ãŒåãããã«åäœããŸããç»é¢ã®å·ŠãŸãã¯å³ã®å¢çä»è¿ã«ã©ã³ãã ãªäœçœ®yã§äœæããããã®åŸãã£ããå
åŽã«ç§»åããŸãããããã®åäœã®ã³ãŒãã¯ããªãœãŒã¹ã«å®è£
ãããã®ãšã»ãŒåãã§ããæåã«åœåãRock
ãæµããå§ããŸããæ¬¡ã®ããã«ãªããŸãããã®ãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã³ãŒãã¯ãã³ãŒããšéåžžã«äŒŒãŠããŸãBoost
ããããããªéãããããŸãã function Rock:new(area, x, y, opts) Rock.super.new(self, area, x, y, opts) local direction = table.random({-1, 1}) self.x = gw/2 + direction*(gw/2 + 48) self.y = random(16, gh - 16) self.w, self.h = 8, 8 self.collider = self.area.world:newPolygonCollider(createIrregularPolygon(8)) self.collider:setPosition(self.x, self.y) self.collider:setObject(self) self.collider:setCollisionClass('Enemy') self.collider:setFixedRotation(false) self.v = -direction*random(20, 40) self.collider:setLinearVelocity(self.v, 0) self.collider:applyAngularImpulse(random(-100, 100)) end
ããã§ã¯ãRectangleColliderã®ä»£ããã«ããªããžã§ã¯ãã¯PolygonColliderã䜿çšããŸããcreateIrregularPolygon
ã§å®çŸ©ããã颿°ã䜿çšããŠããã®ããªãŽã³ã®é ç¹ãäœæãutils.lua
ãŸãããã®é¢æ°ã¯ãäžèŠåãªé·æ¹åœ¢ãæ§æããé ç¹ã®ãªã¹ããè¿ãå¿
èŠããããŸããäžèŠåãªé·æ¹åœ¢ãšã¯ãåã®ããã«èŠãããã®ãæå³ããŸããããã®åé ç¹ã¯äžå¿ãããããã«è¿ããŸãã¯é ãã«ãããåé ç¹éã®è§åºŠããããã«ã©ã³ãã ã«ãªããŸãã颿°ã®å®çŸ©ãéå§ããã«ã¯ã2ã€ã®åŒæ°ãåãåããšèšãããšãã§ããŸãïŒsize
ãšpoint_amount
ã 1ã€ç®ã¯åã®ååŸã瀺ãã2ã€ç®ã¯ããªãŽã³ïŒããªãŽã³ïŒãæ§æãããã€ã³ãã®æ°ã瀺ããŸãã function createIrregularPolygon(size, point_amount) local point_amount = point_amount or 8 end
ããã§point_amount
ãå®çŸ©ãããŠããªãå Žåã®ããã©ã«ãã¯8ã§ãããšèšãããšãã§ããŸããæ¬¡ã«ã§ããããšã¯ããã¹ãŠã®ãã€ã³ããå®çŸ©ããããšã§ããããã¯ã1ãã®ãµã€ã¯ã«ã§å®è¡ã§ããŸããpoint_amount
åãµã€ã¯ã«ã§ãè§åºŠã®ééã«åºã¥ããŠæ¬¡ã®é ç¹ã決å®ããŸããããšãã°ã2çªç®ã®ç¹ã®äœçœ®ã決å®ããããã«ããã®è§åºŠã¯interval 2*angle_interval
ã«ããangle_interval
ãšèšããŸã2*math.pi/point_amount
ãããã§ã¯value ã§ããã€ãŸãããã®å ŽåãçŽ90床ã«ãªããŸãããã®ã³ãŒããèšè¿°ããæ¹ãè«ççã§ãããããã£ãŠã function createIrregularPolygon(size, point_amount) local point_amount = point_amount or 8 local points = {} for i = 1, point_amount do local angle_interval = 2*math.pi/point_amount local distance = size + random(-size/4, size/4) local angle = (i-1)*angle_interval + random(-angle_interval/4, angle_interval/4) table.insert(points, distance*math.cos(angle)) table.insert(points, distance*math.sin(angle)) end return points end
ããã§angle_interval
ãäžã§èª¬æããããã«ãå®çŸ©ããŸãdistance
ããåã®ååŸå
ã®ã©ããã§ãããã®ã©ã³ãã ãªãã»ããã§å®çŸ©-size/4
ã+size/4
ãŸããããã¯ãåé ç¹ãåã®ååšäžã§ã¯ãªããè¿ãã®ã©ããã«ããããšãæå³ããŸãããŸããè§åºŠã®ç¯å²ãå°ãã©ã³ãã åããŠãåã广ãäœæããŸããæåŸã«ãxããã³yã³ã³ããŒãã³ããè¿ããããã€ã³ãã®ãªã¹ãã«è¿œå ããŸããããªãŽã³ã¯ããŒã«ã«ç©ºéã«äœæãããããšã«æ³šæããŠãã ããïŒäžå¿ã0ã0ã§ãããšä»®å®ïŒãã€ãŸããããªãŽã³ã䜿çšããŠãªããžã§ã¯ããæ£ããå Žæã«é
眮ããå¿
èŠããããŸãsetPosition
ããã®ãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒã®ãã1ã€ã®éãã¯ãè¡çªã¯ã©ã¹ã䜿çšããããšEnemy
ã§ããä»ã®ãã¹ãŠã®è¡çªã¯ã©ã¹ãšåæ§ã«ããã®ã¯ã©ã¹ã䜿çšåã«å®çŸ©ããå¿
èŠããããŸãã function Stage:new() ... self.area.world:addCollisionClass('Enemy') ... end
äžè¬ã«ãçžäºã«ç°ãªãè¡çªåäœãæã€ãªããžã§ã¯ãã®ã¿ã€ãã«ã¯ãæ°ããè¡çªã¯ã©ã¹ã远å ããå¿
èŠããããŸããäŸãã°ãæµã¯ãã¬ã€ã€ãŒãç©ççã«ç¡èŠããŸãããã·ã§ã«ã¯ç¡èŠããŸãããä»ã®çš®é¡ã®ãªããžã§ã¯ãã¯ãã®åäœã䜿çšããªããããæ°ããè¡çªã¯ã©ã¹ãäœæããå¿
èŠããããŸããçºå°ç©ã®è¡çªã¯ã©ã¹ããã¬ãŒã€ãŒã®ã¿ãç¡èŠããä»ã®ã·ã§ã«ãç¡èŠããªãå Žåãçºå°ç©ã®è¡çªã¯ã©ã¹ã¯æµã«ã䜿çšã§ããŸããRockãªããžã§ã¯ãã§æåŸã«è¡ãããšã¯ããããã¬ã³ããªã³ã°ããããšã§ããããã¯åãªãããªãŽã³ã§ãããããæ¬¡ã®ããã«ããŠåçŽã«ãã€ã³ããæç»ã§ããŸãlove.graphics.polygon
ã function Rock:draw() love.graphics.setColor(hp_color) local points = {self.collider:getWorldPoints(self.collider.shapes.main:getPoints())} love.graphics.polygon('line', points) love.graphics.setColor(default_color) end
æåã«ãããã®ãã€ã³ããååŸãPolygonShape:getPoints
ãŸãããã€ã³ãã¯ããŒã«ã«åº§æšã§è¿ãããŸãããã°ããŒãã«åº§æšãå¿
èŠãªã®ã§Body:getWorldPoints
ãããŒã«ã«åº§æšãã°ããŒãã«åº§æšã«å€æããããã«ãããã䜿çšããå¿
èŠããããŸãããã®åŸãããªãŽã³ãæãããšãã§ããæåŸ
ã©ããã«åäœããŸããã³ã©ã€ããŒããçŽæ¥ãã€ã³ããååŸããã³ã©ã€ããŒãå転ããããªãŽã³pushRotate
ã§ãããããçµæã®ãã€ã³ãã¯ãã§ã«ãªããžã§ã¯ãã®å転ãèæ
®ããŠãããããBoostãªããžã§ã¯ãã®ããã«ãªããžã§ã¯ãã䜿çšããŠå転ãããå¿
èŠã¯ãããŸãããããããã¹ãŠè¡ããšãã²ãŒã ã¯æ¬¡ã®ããã«ãªããŸããæµã®æŒç¿
110.次ã®ã¿ã¹ã¯ãå®è¡ããŸããhp
éå§å€ã100ã®å±æ§ãRockã¯ã©ã¹ã«è¿œå ããŸãã- Rock
hit
. :
damage
, , 100damage
hp
, hp
0 , Rock «»hp
0 , hit_flash
true, 0,2 â false. hit_flash
true, default_color
, hp_color
.
111.æ°ããã¯ã©ã¹ãäœæããŸãEnemyDeathEffect
ããã®å¹æã¯ãæµãæ»ãã§ãªããžã§ã¯ãProjectileDeathEffect
ãšãŸã£ããåãããã«æ¯ãèããšãã«äœæãããŸãããããã ãã倧ãããRockãªããžã§ã¯ãã®ãµã€ãºã«å¯Ÿå¿ããŸãããã®ãªããžã§ã¯ãã¯ãhp
Rockãªããžã§ã¯ã屿§ã0以äžã«ãªã£ããšãã«äœæããå¿
èŠããããŸãã112.çºå°ç©è¡çªã¯ã©ã¹ãªããžã§ã¯ããšæµè¡çªã¯ã©ã¹ãªããžã§ã¯ãéã®è¡çªã€ãã³ããå®è£
ããŸãããã®å ŽåãProjectileã¯ã©ã¹ã®æŽæ°é¢æ°ã«å®è£
ããå¿
èŠããããŸããã·ã§ã«ãEnemyã¯ã©ã¹ã®ãªããžã§ã¯ãã«ããããããšãã·ã§ã«hit
ã«ãã£ãŠåŒãèµ·ãããããã¡ãŒãžã®éã§æµã®é¢æ°ãåŒã³åºãå¿
èŠããããŸãïŒããã©ã«ãã§ã¯ãã·ã§ã«ã®å±æ§damage
ã¯æåã¯100ã«ãªããŸãïŒããããããå Žåãçºå°ç©ã¯ç¬èªã®é¢æ°ãåŒã³åºãå¿
èŠããããŸãdie
ã113ãPlayerã¯ã©ã¹ã«é¢æ°ã远å ããŸãhit
ããã®é¢æ°ã¯æ¬¡ã®ããšãè¡ãå¿
èŠããããŸãã- åŒæ°ãåãåãå¿
èŠãããã
damage
å®çŸ©ãããŠããªãå Žåãããã©ã«ãå€ã¯10ã§ãã - ãã®é¢æ°ã¯ã屿§
invincible
ãtrueã«èšå®ãã以å€ã¯äœãããŸããã - 4ã8åã®ãªããžã§ã¯ããäœæããå¿
èŠããããŸã
ExplodeParticle
- 颿°
addHP
ïŒãŸãã¯removeHP
ã远å ããããšã決å®ããå ŽåïŒã¯ã屿§damage
ãåãåããããã䜿çšããŠPlayerãªããžã§ã¯ãã®HPãäžããå¿
èŠããããŸãã颿°addHP
ïŒãŸãã¯removeHP
ïŒã®å
éšã§ãhp
0以äžã«ãªããã¬ãŒã€ãŒãæ»ãã å Žåã®ç¶æ³ãåŠçããæ¹æ³ãå®è£
ããå¿
èŠããããŸãã
ããã«ãæ¬¡ã®æ¡ä»¶ä»ãååŒã¯å
¬æ£ã§ãªããã°ãªããŸããã- 30,
invincible
true, â false. , 0,2 6, , 0,5 0,25. , invisible
true false 0,04 , invincible
true. invisible
true, Player . - 30, 0,1 6, , 0,25 0,75.
ãã®é¢æ°hit
ã¯ããã¬ãŒã€ãŒãæµãšè¡çªãããšãã«åŒã³åºãå¿
èŠããããŸããæµãšè¡çªããå Žåããã¬ã€ã€ãŒã«30ã®ãã¡ãŒãžãäžããå¿
èŠããããŸãã
ãããã®4ã€ã®æŒç¿ãå®äºãããšããã¬ãŒã€ãŒãæå°ç©ãæµã®å²©ã®éã®çžäºäœçšã«å¿
èŠãªãã®ããã¹ãŠæãã¯ãã§ãããããã®çžäºäœçšã¯ä»ã®æµã«é©çšãããŸãããã¹ãŠæ¬¡ã®ããã«ãªããŸããæµã®çºå°ç©
ããã§ãæµãšã®äœæ¥ã®å¥ã®éšå-ç ²åŒŸãçºå°ããæµã®äœæã«éäžã§ããŸãããã®ãããªæ©äŒã¯äžéšã®æµãå©çšã§ããããã«ãªãã®ã§ãProjectileã«äŒŒãŠãããæµã䜿çšãããªããžã§ã¯ããäœæããå¿
èŠããããŸãããããè¡ãã«ã¯ããªããžã§ã¯ããäœæããŸãEnemyProjectile
ãã³ãŒããã³ããŒããŠå°ã倿Žããã ãã§ãæåã«ãã®ãªããžã§ã¯ããäœæã§ããŸãProjectile
ããããã®ãªããžã§ã¯ãã®äž¡æ¹ã«ã¯å€ãã®å
±éç¹ããããŸããå
±éã®æ¯ãèããããå
±éã®çºå°ç©ãªããžã§ã¯ãã«æœè±¡åã§ããŸãããå®éã«ã¯ã²ãŒã ã«ã¯2çš®é¡ã®ã·ã§ã«ãããªããããããã¯å¿
èŠãããŸãããã³ããŒåŸã次ã®å€æŽãè¡ãå¿
èŠããããŸãã function EnemyProjectile:new(...) ... self.collider:setCollisionClass('EnemyProjectile') end
EnemyProjectileè¡çªã¯ã©ã¹ãEnemyProjectileã§ãªããã°ãªããŸãããEnemyProjectileãªããžã§ã¯ããä»ã®EnemyProjectileãProjectileãããã³Playerãç¡èŠããããã«ããŸãããããã£ãŠããã®ç®æšã«å¯Ÿå¿ããè¡çªã¯ã©ã¹ã远å ããŸãã function Stage:new() ... self.area.world:addCollisionClass('EnemyProjectile', {ignores = {'EnemyProjectile', 'Projectile', 'Enemy'}}) end
倿Žããå¿
èŠãããå¥ã®éèŠãªåŽé¢ã¯æå·ã§ãããã¬ã€ã€ãŒãçºå°ããéåžžã®çºå°ç©ã¯100ãã¡ãŒãžãäžããæµã®ç ²åŒŸã¯10ãã¡ãŒãžãäžããŸãã function EnemyProjectile:new(...) ... self.damage = 10 end
ãŸããPlayerãšç«¶åããããä»ã®æµãšç«¶åããªãããã«ã¯ãæµãçºå°ããã·ã§ã«ãå¿
èŠã§ãããããã£ãŠãProjectileãªããžã§ã¯ãã§äœ¿çšãããè¡çªã³ãŒããååŸããPlayerèªäœã«ã©ããããŸãã function EnemyProjectile:update(dt) ... if self.collider:enter('Player') then local collision_data = self.collider:getEnterCollisionData('Player') ... end
æåŸã«ããã®ãªããžã§ã¯ããèµ€çœã§ã¯ãªãå®å
šã«èµ€ã«ããããšã§ããã¬ãŒã€ãŒãèªåã®ã·ã§ã«ãæµã®ãã®ãšåºå¥ã§ããããã«ããŸãã function EnemyProjectile:draw() love.graphics.setColor(hp_color) ... love.graphics.setColor(default_color) end
ãããã®å°ããªå€æŽããã¹ãŠè¡ã£ãã®ã§ãEnemyProjectileãªããžã§ã¯ããäœæã§ããŸãããæ¬¡ã«ãããã䜿çšããæµãäœæããå¿
èŠããããŸãïŒæµãæã€
æµã®ã·ã¥ãŒã¿ãŒã¯æ¬¡ã®ããã«ãªããŸããã芧ã®ãšãããæåã¯å°ããªå¹æãåçŸãããæ¬¡ã«ç ²åŒŸãçºå°ãããŸããçºå°ç©ã¯ãã¬ãŒã€ãŒãšåãããã«èŠããŸãããå®å
šã«èµ€ãã ãã§ããRockãªããžã§ã¯ãããã³ãŒããã³ããŒããããšã§ããã®æµã®äœæãââéå§ã§ããŸãããã®æµïŒãããŠå®éãã¹ãŠã®æµïŒã¯ãç»é¢ã®å·ŠãŸãã¯å³ã«çŸããŠãããã£ãããšå
åŽã«ç§»åãããšããå
±éã®ç¹æ§ãæã¡ãŸããRockãªããžã§ã¯ãã«ã¯ãã§ã«ãã®ã³ãŒããå«ãŸããŠãããããããããå§ããŸããã³ãŒããã³ããŒããåŸãå°ããªå€æŽãå ããå¿
èŠããããŸãã function Shooter:new(...) ... self.w, self.h = 12, 6 self.collider = self.area.world:newPolygonCollider( {self.w, 0, -self.w/2, self.h, -self.w, 0, -self.w/2, -self.h}) end
æµã®ã·ã¥ãŒã¿ãŒã®å¹
ãé«ããäžéšã®å€ã¯ãããã¯ãšã¯ç°ãªããŸããç³ã§ã¯ãåçŽã«äžèŠåãªå€è§åœ¢ãäœæããŸãããããã¬ã€ã€ãŒãèªåãã©ãã«ç§»åããããæ¬èœçã«çè§£ã§ããããã«ããã®æµã«ã¯ã¯ã£ãããšåºå¥ã§ããå°ã£ã圢ç¶ãäžããå¿
èŠããããŸããããã§ã®ããŒã¯ã®èšå®ã¯ãè¹ã®èšèšããã»ã¹ã«äŒŒãŠããŸãããããã£ãŠãå¿
èŠã«å¿ããŠãæµã®å€èгã倿ŽããŠãããæ¥å³»ã«ããããšãã§ããŸãã function Shooter:new(...) ... self.collider:setFixedRotation(false) self.collider:setAngle(direction == 1 and 0 or math.pi) self.collider:setFixedRotation(true) end
ãŸãã以äžã倿Žããå¿
èŠããããŸããç³ãšã¯ç°ãªãããªããžã§ã¯ãã®é床ãèšå®ããã ãã§ã¯ååã§ã¯ãããŸããããŸããç©çã³ã©ã€ããŒãæ£ããæ¹åãåãããã«è§åºŠãèšå®ããå¿
èŠããããŸãããããè¡ãã«ã¯ãæåã«äžå®ã®å転ãç¡å¹ã«ãïŒãã以å€ã®å Žåãè§åºŠã®èšå®ã¯æ©èœããŸããïŒãè§åºŠã倿ŽããŠãããäžå®ã®å転ãåã³çã«ããå¿
èŠããããŸããäœããè¡çªãããšãã«ã³ã©ã€ããŒãå転ãããããªããããå転ãåã³æ°žç¶åããŸããåãã®æ¹åã«åããŠããå¿
èŠããããŸããæåådirection == 1 and math.pi or 0
ã¯ãLuaã®äžé
æŒç®åã®å®è£
ã§ããä»ã®èšèªã§ã¯ã次ã®ããã«ãªã(direction == 1) ? math.pi : 0
ãŸãã第2éšãšç¬¬4éšã®æŒç¿ã§ã¯ãããããè©³çŽ°ã«æ€èšã§ãããšæããŸããæ¬è³ªçã«ãããã§ã¯æ¬¡ã®ããšãèµ·ãããŸããdirection
1ã«çããïŒæµãå³åŽã«è¡šç€ºãããå·ŠåŽã«åããããïŒå Žåãæåã®æ¡ä»¶ä»ãæ§æã¯trueã«è§£æãããŸããã€ãŸãããååŸããtrue and math.pi or 0
ãŸããæ³šæã®å·è¡ã®ããã«and
ããããŠor
æåã®æå¿true and math.pi
çµæãšããŠãæã
ã¯æã£ãŠããã ãããã§ãmath.pi or 0
äž¡æ¹ã®èŠçŽ ãçã§ãããšãããããŠã®ã§ããã®ãªã¿ãŒã³ã«Math.PIãor
æåã®ãã®ãè¿ããŸããäžæ¹ãdirection
-1ã®å Žåãæåã®æ¡ä»¶ä»ãæ§æã¯falseã«è§£æããfalse and math.pi or 0
ãæåããŸããã€ãŸãfalse or 0
0ã«ãªãor
ãŸããæåã®èŠçŽ ãfalseã®å Žåã2çªç®ã®èŠçŽ ãè¿ãããããã§ããããããã¹ãŠã念é ã«çœ®ããŠãã²ãŒã å
ã§Shooterãªããžã§ã¯ãã®äœæãéå§ã§ããŸãããããã¯æ¬¡ã®ããã«ãªããŸããæ¬¡ã«ãæ»æåã®å¹æãäœæããå¿
èŠããããŸããéåžžãã»ãšãã©ã®ã²ãŒã ã§ã¯ãæµãæ»æããããšãããšãäœãããã¬ã€ã€ãŒã«éç¥ãããŸããã»ãšãã©ã®å Žåãããã¯ã¢ãã¡ãŒã·ã§ã³ã§ããããšãã§ã¯ãã§ããããŸãããã®å ŽåãåçŽãªããã£ãŒãžã³ã°ããšãã§ã¯ãã䜿çšããŸãããã®ãšãã§ã¯ãã§ã¯ãçºå°ç©ãé£ã¶ç¹ãŸã§å€ãã®ç²åãåžåãããŸããé«ã¬ãã«ã§ã®å®è£
æ¹æ³ã¯æ¬¡ã®ãšããã§ãã function Player:new(...) ... self.timer:every(random(3, 5), function()
ããã¯ã3ã5ç§ã®ééã§ãåæµã®å°æãæ°ããçºå°ç©ãçºå°ããããšãæå³ããŸããããã¯ããšãã§ã¯ãPreAttackEffect
ã1ç§éå®äºããåŸã«çºçããŸããåæ§ã®å¹æã¯ãç²åã§æ¬¡ã®ããã«æ©èœããŸããææ°ãã¬ãŒã¹ã®å Žåãåãã¬ãŒã ãŸãã¯ãã¬ãŒã ãéããŠãç¹å®ã®ã¿ã€ãã®ç²åãäœæããããã®å¹æãæ§æãããŸãããã®å ŽåãããŒãã£ã¯ã«ã¯ã®ååã§äœæããTargetParticle
ãŸãããããã®ããŒãã£ã¯ã«ã¯ãã¿ãŒã²ãããšããŠå®çŸ©ãããã€ã³ããŸã§ç§»åãããã°ããããŠããããŸãã¯ç®æšã«å°éãããšãã«æ¶æ»
ããŸãã function TargetParticle:new(area, x, y, opts) TargetParticle.super.new(self, area, x, y, opts) self.r = opts.r or random(2, 3) self.timer:tween(opts.d or random(0.1, 0.3), self, {r = 0, x = self.target_x, y = self.target_y}, 'out-cubic', function() self.dead = true end) end function TargetParticle:draw() love.graphics.setColor(self.color) draft:rhombus(self.x, self.y, 2*self.r, 2*self.r, 'fill') love.graphics.setColor(default_color) end
ããã§ã¯ãåããŒãã£ã¯ã«ã«ã€ããŠãæéã®çµéãšãšãã«d
ïŒãŸãã¯0.1ã0.3ç§ã®ã©ã³ãã ãªå€ïŒããã¥ã€ãŒã³ã¯ã«ç§»è¡ãtarget_x, target_y
ãããŒãã£ã¯ã«ããã®äœçœ®ã«å°éãããšæ¶æ»
ããŸããããŒãã£ã¯ã«ã¯è±åœ¢ãšããŠãæç»ãããŸãïŒä»¥åã«äœæãããšãã§ã¯ãã®1ã€ãšããŠïŒããéåžžã«å°ãããæéãšãšãã«ããã«å°ãããªããããåãŸãã¯æ£æ¹åœ¢ãšããŠæç»ããããšãã§ããŸãããããã®ãªããžã§ã¯ãPreAttackEffect
ãæ¬¡ã®ããã«äœæããŸãã function PreAttackEffect:new(...) ... self.timer:every(0.02, function() self.area:addGameObject('TargetParticle', self.x + random(-20, 20), self.y + random(-20, 20), {target_x = self.x, target_y = self.y, color = self.color}) end) end
ãã®ãããããã§ã¯ãäœçœ®ã®åšãã®ã©ã³ãã ãªå Žæã«0.02ç§ããšã«ïŒã»ãŒãã¹ãŠã®ãã¬ãŒã ã§ïŒ1ã€ã®ããŒãã£ã¯ã«ãäœæãtarget_x, target_y
ããšãã§ã¯ãèªäœïŒã€ãŸããè¹ã®è¹éŠïŒã®äœçœ®å€ã«å±æ§ãèšå®ããŸããæ¬¡ã®ããã«æã
ã¯PreAttackEffectãäœæããŸããShooter
function Shooter:new(...) ... self.timer:every(random(3, 5), function() self.area:addGameObject('PreAttackEffect', self.x + 1.4*self.w*math.cos(self.collider:getAngle()), self.y + 1.4*self.w*math.sin(self.collider:getAngle()), {shooter = self, color = hp_color, duration = 1}) self.timer:after(1, function() end) end) end
èšå®ããåæäœçœ®ã¯ãShooterãªããžã§ã¯ãã®éŒ»ã®äžã«ããå¿
èŠããããŸãããã®ãããæ¢ã«é©çšããmath.cosãšmath.sinã§éåžžã®ãã¿ãŒã³ã䜿çšããå¯èœãªäž¡æ¹ã®è§åºŠïŒ0ãšmath.piïŒãèæ
®ããããšãã§ããŸããduration
PreAttackEffectã®æå¹æéãå¶åŸ¡ãã屿§ãæž¡ãããšãã§ããŸããããã§ã¯æ¬¡ã®ããšãã§ããŸãã function PreAttackEffect:new(...) ... self.timer:after(self.duration - self.duration/4, function() self.dead = true end) end
ç§ã¯duration
èªåèªèº«ããã³ã³ãããŒã©ãŒãªããžã§ã¯ãããšåŒã¶ãªããžã§ã¯ããªã®ã§ã䜿çšããŸãããããšãã°ãæç»é¢æ°ã«ã¯äœããããŸãããã€ãŸããã²ãŒã ã§ã¯è¡šç€ºãããŸãããTargetParticle
圌ãäœæããããã«æ³šæãããªããžã§ã¯ãã®ã¿ã衚瀺ãããŸãããããã®ãªããžã§ã¯ãã¯ã0.1ç§ãã0.3ç§ãŸã§ã®ã©ã³ãã ãªå¯¿åœãæã¡ãŸããã€ãŸããçºå°ç©ã§æã£ããšãã«æåŸã®ããŒãã£ã¯ã«ãããã«çµãããããå Žåããã®ãªããžã§ã¯ãã¯ãã®æç¶æéãã0.1-0.3ç§é
ããŠæ»ã«ãŸãã 1ç§ã§ã 0.75ïŒæé-æé/ 4ïŒã«çããããããšã«ããŸãããã代ããã«0.9ç§ã«è¿ãå¥ã®æ°å€ã䜿çšã§ããŸããããã§ã²ãŒã ãå®è¡ãããšã次ã®ããã«ãªããŸãããããŠããã¹ãŠãéåžžã«ããŸãæ©èœããŸããããããããèŠããšãã¿ãŒã²ããããŒãã£ã¯ã«ã®äœçœ®ïŒPreAttackEffectãªããžã§ã¯ãã®äœçœ®ïŒãåºå®ããããŸãŸã§ãããã·ã¥ãŒã¿ãŒã«åŸããªãããšãããããŸããããã¯ããã¬ãŒã€ãŒã®ShootEffectãªããžã§ã¯ããä¿®æ£ããã®ãšåãæ¹æ³ã§ä¿®æ£ã§ããŸããshooter
PreAttackEffectãªããžã§ã¯ããäœæããShooterãªããžã§ã¯ããæã屿§ãæ¢ã«ããããããã®èŠªãªããžã§ã¯ãã®äœçœ®ã«åºã¥ããŠPreAttackEffectã®äœçœ®ãæŽæ°ããã ãshooter
ã§ãã function PreAttackEffect:update(dt) ... if self.shooter and not self.shooter.dead then self.x = self.shooter.x + 1.4*self.shooter.w*math.cos(self.shooter.collider:getAngle()) self.y = self.shooter.y + 1.4*self.shooter.w*math.sin(self.shooter.collider:getAngle()) end end
ããã§ã¯ãåãã¬ãŒã ããã®ãªããžã§ã¯ãã®äœçœ®ãæŽæ°ããŠããªããžã§ã¯ããäœæããShooterãªããžã§ã¯ãã®éŒ»ã®äžã«é
眮ããŸããã²ãŒã ãå®è¡ãããšã次ã®ããã«ãªããŸããæŽæ°ã³ãŒãã®éèŠãªåŽé¢ã¯ãã®éšånot self.shooter.dead
ã§ãããã®ããã«çžäºã«å
éšã®ãªããžã§ã¯ããåç
§ããå Žåãäžæ¹ã®ãªããžã§ã¯ããæ¶æ»
ããŠããããäžæ¹ã®ãªããžã§ã¯ãããã®ãªããžã§ã¯ããžã®ãªã³ã¯ãä¿åããããšããããŸããããšãã°ãPreAttackEffectãªããžã§ã¯ãã®æå¹æéã¯0.75ç§ã§ãããäœæããæ¶æ»
ãŸã§ã®éãäœæããShooterãªããžã§ã¯ãã¯ãã¬ã€ã€ãŒã«ãã£ãŠæ®ºãããå¯èœæ§ããããŸãããããçºçãããšãåé¡ãçºçããå¯èœæ§ããããŸããç§ãã¡ã®å Žåãåé¡ã¯collider
ãShooterãªããžã§ã¯ãã®å±æ§ã«ã¢ã¯ã»ã¹ã§ããããšã§ãããã®å±æ§ã¯ãShooterãªããžã§ã¯ããæ¶æ»
ãããšç Žæ£ãããŸãããããŠããã®ãªããžã§ã¯ããç Žå£ãããå Žåãããã¯ããååšããªããããäœãã§ããŸãããå®è¡ããããšãããšgetAngle
ãã®åŸãã²ãŒã ã¯èœã¡ãŸãããã®ãããªåé¡ã解決ããå
±éã®ã·ã¹ãã ãéçºããããšã¯ã§ããŸãããå®éã«ã¯å¿
èŠã ãšã¯æããŸãããä»ã®ãšããããã®æ¹æ³ã§ãªããžã§ã¯ããåç
§ãããšãã¯ããã§ã«æ»ãã§ããå¯èœæ§ã®ãããªããžã§ã¯ãã«ã¢ã¯ã»ã¹ããããšããªãããã«æ³šæããã ãã§ååã§ãããããŠæåŸã«ãEnemyProjectileãªããžã§ã¯ããäœæããæåŸã®éšåã§ãããããéåžžã«ç°¡åã«æäœããŠäœæããŸãããéåžžã©ãããä»ã®ãªããžã§ã¯ããäœæããŸãããç¬èªã®å±æ§ã䜿çšããŸãã function Shooter:new(...) ... self.timer:every(random(3, 5), function() ... self.timer:after(1, function() self.area:addGameObject('EnemyProjectile', self.x + 1.4*self.w*math.cos(self.collider:getAngle()), self.y + 1.4*self.w*math.sin(self.collider:getAngle()), {r = math.atan2(current_room.player.y - self.y, current_room.player.x - self.x), v = random(80, 100), s = 3.5}) end) end) end
ããã§ã¯ãPreAttackEffectãäœæããã®ãšåãäœçœ®ã«çºå°ç©ãäœæãããã®é床ã«80ãš100ã®ã©ã³ãã ãªå€ãå²ãåœãŠãŸãããŸããããã©ã«ãå€ã«å¯ŸããŠãµã€ãºããããã«å€§ããããŸããæãéèŠãªéšåã¯ããã®è§åºŠïŒr
屿§ïŒããã¬ãŒã€ãŒã®æ¹åãæããŠããããšã§ããæã
ã¯ã®è§åºŠãååŸããããšããäžè¬çãªã±ãŒã¹ã§ã¯ãsource
ã¢ãããããããã«target
ãæã
ã¯æ¬¡ã®ããšãè¡ãå¿
èŠããããŸãã angle = math.atan2(target.y - source.y, target.x - source.x)
ã ããããããããªããžã§ã¯ããäœæããåŸãããã¯ãã¬ãŒã€ãŒã«åãããã圌ã«åãã£ãŠåãå§ããŸããæ¬¡ã®ããã«ãªããŸãããã®ã¢ãã¡ãŒã·ã§ã³ããã¥ãŒããªã¢ã«ã®ãã®éšåã®æåã®ã¢ãã¡ãŒã·ã§ã³ãšæ¯èŒãããšãããããªéããããããŸããã·ã§ã«ã¯ããã¬ã€ã€ãŒã«çŽæ¥é£è¡ããã®ã§ã¯ãªãããã¬ã€ã€ãŒã«åãã£ãŠãã£ãããšåã£ãŠããæéããããŸããããã¯ãããã·ãããŒãã³ã°ã¹ãã«ãšåãã³ãŒããã©ã°ã¡ã³ãã䜿çšããŸããããã¯ãæéã®çµéãšãšãã«è¿œå ãããã®ã§ãåŸã§äœ¿çšããŸããåŸã
ã«ãEnemyProjectileãªããžã§ã¯ãã«ããŸããŸãªæ©èœã远å ããŠãå€ãã®ç°ãªãæµã«é©çšã§ããããã«ããŸãããã ãããã®ãã¹ãŠã®æ©èœã¯ããã¬ãŒã€ãŒã®ããã·ãã¹ãã«ãšããŠæ©èœãããããProjectileãªããžã§ã¯ãã«æåã«å®è£
ãããŸããããšãã°ãã·ã§ã«ããã¬ã€ã€ãŒã®åšãã«åãååçãªã¹ãã«ããããŸããå®è£
ããããã³ãŒããEnemyProjectileãªããžã§ã¯ãã«ã³ããŒãã颿°ã䜿çšããŠæµãå®è£
ã§ããŸãã圌ã¯ç ²åŒŸãæã¡ãŸãã-圌ãã¯åœŒã®åšããæåããŸãããã®ããã«ããŠãå€ãã®æµãäœæããŸãããã®ããããã¬ã€ã€ãŒã«ååçãªã¹ãã«ãäœæãããšãã¯ããã®éšåãæŒç¿ãšããŠæ®ããŸãã2äººã®æµïŒããã¯ãšã·ã¥ãŒã¿ãŒïŒã§åæ¢ããŠããéãEnemyProjectileããã®ãŸãŸã«ããŠãä»ã®åŽé¢ã«é²ã¿ãŸãããã ããåŸã§ã²ãŒã ã«æ©èœã远å ãããšãæ°ããæµãäœæããããã«æ»ããŸããEnemyProjectile / Shooterã®ç·Žç¿
114. ProjectileãšEnemyProjectileéã®è¡çªã€ãã³ããå®è£
ããŸããEnemyProjectileã¯ã©ã¹ã§ãProjectileã¯ã©ã¹ã®ãªããžã§ã¯ãã«å
¥ããšãdie
äž¡æ¹ã®ãªããžã§ã¯ãã®é¢æ°ãåŒã³åºãããäž¡æ¹ãç Žæ£ãããããšã確èªããŠãã ããã115.direction
Shooterã¯ã©ã¹ã®å±æ§åã¯æ··ä¹±ããŸããïŒãããããªããã©ã®ããã«ååã倿Žããå¿
èŠããããŸããïŒããã§ãªãå Žåããªãã§ããïŒ