From 60a89ed12827372c6b632c1d5e069fae842763e7 Mon Sep 17 00:00:00 2001 From: Daanish Date: Mon, 30 Mar 2026 16:31:08 +0000 Subject: [PATCH] Enhance enemy AI and introduce Force class: update speed dynamics based on Lorentz field effects, refactor enemy spawning to utilize Force, and add sprite loading for Force. --- assets/images/force.aseprite | Bin 0 -> 708 bytes assets/images/force.png | Bin 0 -> 811 bytes game/enemy/ai.rb | 24 ++++++++++++++++++++---- game/enemy/base.rb | 33 ++++++++++++++++++++++++++------- game/enemy/force.rb | 11 +++++++++++ game/enemy/handler.rb | 4 ++-- game/weapons/lorentz_field.rb | 2 ++ 7 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 assets/images/force.aseprite create mode 100644 assets/images/force.png create mode 100644 game/enemy/force.rb diff --git a/assets/images/force.aseprite b/assets/images/force.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..f4479cf5b2f0517365edf084f70cfa2f89ce0190 GIT binary patch literal 708 zcmX@Y#K7=iDISz_Vy(P2~E*?50hvAk3ak5^zA?Y|No!8c6&=*duCQvWLQv{Q`Z_J zqnqK$*Q{dQ;QS~r!q1yu!0=Hz`*dI38o4ZcolQ* zPTT0kVkpq|UNGl~`v&10zc)1usc)yfW)a;epyRUPg4d4a8w7q=chxd$Zxpz4T;TEF z#Qz`CPaN~UcB*y$-7{xvW}ordWIl6B?CWglbp|S@o8oRIho4q$F7oG2&s}O`pwZKx z=DTC{-j+A`?v1B&Qqt9$g5Ap_Vw)FUE8zdPH5#RmgMYeeW9IOeGKk= zUbuVKyItE~d;jOTEukiHf4=#@zD@`hVf`4C&u{=ReMm`4ne=uUY@yKK`lc-yHh9)2^2$^6iRmE7@Sb z$6R-^;hVQpe%uxiH(O(EF#UDw`ezrOiByKkN3%aW*7fn>n-@DDe6$I*U(5P@>DMK5 z_XPZ}>r1&+wd(A=_Fr|e)|IEWybhh6>Sj6BrfK@BvjJ=0%&6Qb_4(};o8bDRXKwzJ ozWi-%s#uZ#BI6@(+Na1GYW9Ub+8=l=Z%V58sd)RT6M9br0M`!%>Hq)$ literal 0 HcmV?d00001 diff --git a/assets/images/force.png b/assets/images/force.png new file mode 100644 index 0000000000000000000000000000000000000000..594e7f4d1afd6af7bfb58e6c5021fc60d3259c5a GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0y~yU=U?sU{K&-V_;zTyTG`Efq{XsILO_JVcj{ImkbO{ zPd!~6Lp(b7PV@JWb`&|b|L&Hhw@!2Ag(-_M$2HCP62zIQ5s`6pmNWO%IbIuYIP-DO z+w=XE=M85*U60F?m#}l+wr6~)*|H!YV&RSE4O<=^I~#Q)C_p=9d%MNsbu)WA+wD#y z-rw`{ta<*u*_;=ab~ZhU6FFSYEX;aR*FRN{rFgE^D(%Xar*rg=ZSsBgN89nhu1U-9 zCt9}e?9XRlFuv@$#-_&Yj~@4#n9dyI*dRmWxi0?o`V0pwI+crZx!>QbV~jM>c^)NV zJT+?D$)(<_xEXB!?ltgxRC30mQ+aByvd;5>d8alk+kQS%Yc~UfM~m`4!?k$~3|gyC zpV?zHwMtj8FTpqV<4?KNXBsn7#iw1FwTo%3!h?fX_gB>a7u(WwVUx%8fVBz--gYaB z?d_cSad*M*qzhb34@~qpOQi~aCowcUpQ%$Se1GXwySmE7oU`t+ zYtG257MXgW?~|pgW7bQ7zzKI|zEs&)_useHwANaHBj2;L>B+Svf;>zjI$V=}KY3{@ zaXh)huVq%FAG2xgY|R79r!ai|suc8id*V$sb*@RXCr@AS_B~V03G+@9=eWoet#7hZ zem+(YojZB@EY>={j>~=5I(DW7OS-eSutF(qDRoek=@Bo8k2J>!X?1 zGY{On?O2l3RrkB=Zsr5ODuHwN_?r}(lTUSTKhbh!y}IdE zmHj8hjNiL2d@E0s={F6H``@;>`LI|)T;vj_iY=AdbN0@C_Hy!k_owUa|N3l5ogH(# zPbv4+l`qp+SEp{>+}g z-(Kg1%}b*XiXWN-xfJT^GOj#lH+auF;mG;<>fKFWPW{fk`K-IFPHf65o;&&J-=rA+ aG43=84STnXS%QIqfx*+&&t;ucLK6Th5rSC& literal 0 HcmV?d00001 diff --git a/game/enemy/ai.rb b/game/enemy/ai.rb index dacb1d4..59cf532 100644 --- a/game/enemy/ai.rb +++ b/game/enemy/ai.rb @@ -1,6 +1,6 @@ class EnemyAI AGGRO_RADIUS = 2000 - SPEED = 120.0 + BASE_SPEED = 130.0 CORNER_OFFSET = 35 # how far from tile center to place corner waypoint def initialize(enemy, type) @@ -10,12 +10,28 @@ class EnemyAI @waypoints = [] # actual world positions to move through @last_player_tile = nil @avoiding_obstacle = false + @speed = BASE_SPEED + @lorentz_effect_active = false + + $bus.on(:lorentz_field) do + @lorentz_effect_active = true + end + + $bus.on(:lorentz_field_end) do + @lorentz_effect_active = false + end end def update(player_x, player_y, dt) - distance = Gosu.distance(@enemy.x, @enemy.y, player_x, player_y) + distance = Math.sqrt((player_x - @enemy.x)**2 + (player_y - @enemy.y)**2) return unless distance < AGGRO_RADIUS + if @lorentz_effect_active && distance < 230 + @speed = BASE_SPEED * 0.3 + else + @speed = BASE_SPEED + end + player_tile = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round) enemy_tile = [(@enemy.x - 90) / 120, (@enemy.y - 90) / 120].map(&:round) @@ -135,8 +151,8 @@ class EnemyAI def move_towards(target_x, target_y, dt) angle = Gosu.angle(@enemy.x, @enemy.y, target_x, target_y) - dx = Gosu.offset_x(angle, SPEED * dt) - dy = Gosu.offset_y(angle, SPEED * dt) + dx = Gosu.offset_x(angle, @speed * dt) + dy = Gosu.offset_y(angle, @speed * dt) @enemy.x += dx @enemy.y += dy diff --git a/game/enemy/base.rb b/game/enemy/base.rb index 6e85c23..4ef1883 100644 --- a/game/enemy/base.rb +++ b/game/enemy/base.rb @@ -3,6 +3,23 @@ require_relative 'ai' class Enemy attr_accessor :x, :y, :w, :h + def self.load(path, w, h, s) + # Once artwork is done need to load each animation here. + # But as artwork takes time, for now just load a single image. + @sprite = Gosu::Image.new(path, retro: true) + @i_w = w + @i_h = h + @s = s + end + + def self.sprite + @sprite + end + + def self.frame_size + [@i_w, @i_h, @s] + end + def initialize(x, y) @x = x @y = y @@ -36,15 +53,17 @@ class Enemy screen_x = @x - cam_x screen_y = @y - cam_y - Gosu.draw_rect( - screen_x - @w / 2, - screen_y - @h / 2, - @w, - @h, - Gosu::Color::RED, - screen_y - @h / 2 + + self.class.sprite.draw( + screen_x - self.class.frame_size[0], + screen_y - self.class.frame_size[1], + screen_y - self.class.frame_size[1], + self.class.frame_size[2], + self.class.frame_size[2] ) + Gosu.draw_rect(screen_x - @w / 2, screen_y - @h / 2, @w, @h, Gosu::Color.new(0x40FF0000), Float::INFINITY) if $bus.get(:settings, :debug) + @ai.draw end end \ No newline at end of file diff --git a/game/enemy/force.rb b/game/enemy/force.rb new file mode 100644 index 0000000..546245d --- /dev/null +++ b/game/enemy/force.rb @@ -0,0 +1,11 @@ +require_relative 'base' + +class Force < Enemy + load 'assets/images/force.png', 21, 32, 1.7 + + def initialize(x, y) + super + @w = 20 + @h = 20 + end +end \ No newline at end of file diff --git a/game/enemy/handler.rb b/game/enemy/handler.rb index 13f211a..0e97375 100644 --- a/game/enemy/handler.rb +++ b/game/enemy/handler.rb @@ -1,4 +1,4 @@ -require_relative 'base' +require_relative 'force' class EnemyHandler def initialize @@ -14,7 +14,7 @@ class EnemyHandler # For now, just spawn a single enemy at a fixed location start_room_coords = $bus.get(:start_room_coords) if @enemies.empty? - @enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) + @enemies << Force.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) end end diff --git a/game/weapons/lorentz_field.rb b/game/weapons/lorentz_field.rb index cec3af1..3b757f0 100644 --- a/game/weapons/lorentz_field.rb +++ b/game/weapons/lorentz_field.rb @@ -32,6 +32,7 @@ class LorentzField $bus.emit(:consume, :lorentz_field, 1) @active = true @time = 0 + $bus.emit(:lorentz_field) end def update(dt) @@ -41,6 +42,7 @@ class LorentzField if @time >= BASE_TIME @time = 0 @active = false + $bus.emit(:lorentz_field_end) end end