Enemy attack patterns

Monkey Forums/Monkey Programming/Enemy attack patterns

Sensei(Posted 2014) [#1]
Hoping some of you brainy guys can help point me in the right direction here.
I've been working on a bullet-hell shooter for some time now and I've created my own Enemy class that does various things. However, I would like to add an additional feature where I can set a parameter to have the enemy utilize the chosen attack pattern based on the parameter set.
Only problem is, I'm not a brainy mathematician and haven't had much luck finding information on Google about attack patterns to use.
For example, a sine-wave type attack move, circular 8 shape move, etc etc.

So does anyone have anything of use to help this hapless person out? :)


Gerry Quinn(Posted 2014) [#2]
My first thought is that I would need to know whether single enemies or groups are involved. And secondly, should it control missile firing patterns also? There is the question of whether there is a constant relative motion to the player also. For example, is the player moving along at a steady or steady-ish pace while the enemy moves in circles about a particular point?

What I'm saying is that the game is going to have a particular structure that the patterns will be variations on, and you can't really define the patterns until you know that structure.


SLotman(Posted 2014) [#3]
For example, a sine-wave type attack move, circular 8 shape move, etc etc.

Those patterns can be easily achieved with sin/cosin in math - you just make the enemy position x + cos(angle)*radius, y + sin(angle)*radius and off you go :)
(beware that x and y would be the center of the circle!)

(for example to give a zig-zag movement while moving down, just use x + cos(angle)*radius,y and keep updanting angle from 0 to 360, and increasing y position)


Sensei(Posted 2014) [#4]
Thanks @Slotman. That's pretty much what I'm looking for, so I'll start playing with your examples later this evening.
@Gerry: Though the player remains on screen, the background assets create the illusion of movement through a given level, but there's no actual scrolling happening. I run a timer, which triggers when enemies execute their attacks based on a predetermined time, ie the counter always starts at 0 at the beginning of the game, but say, the timer hits 200, then the first predetermined enemies will start their movements, which makes them appear to the user at a given point of illusionary movement through the level.
I don't think that's really too much of an issue anyway, as Slotman's example pretty much provides the type of thing I'm after.
I can provide more details if you are interested (this evening at home) and if that'll help, so let me know.


Gerry Quinn(Posted 2014) [#5]
Well, that is the sort of thing I was thinking about,

My impression is that the enemy movement is a combination of a linear movement towards the player or more likely the horizontal or vertical line of the player, combined with an individual motion. I think it would simplify things if you added these together.

For example, say the player is apparently moving up the screen, and an enemy is activated. It gets a linear movement downwards at the apparent speed that the player moves up. Superimposed on that, you put another motion, which could be anything. For example a circular motion. Then you would have:

' Start (a bit off screen)
enemyBasePosition = ( xStart, yStart )
time = 0

' Basic movement
enemyBasePosition = ( xStart, yStart + VERT_SPEED * time )

' Individual movement (there's a correct adjective for this that's on the tip of my tongue)
angle = time / ROT_SPEED
indivDelta = ( ROT_RADIUS * cos( angle ), ROT_RADIUS * sin( angle )

' Actual position
( enemyBasePosition.x + indivDelta.x, enemyBasePosition.y + indivDelta.y )

So this enemy is moving down the screen, moving in circles around an object on your virtual background.

Anyway, that's how I'd approach it.


therevills(Posted 2014) [#6]
You could use a simple way point system:


Also Samah loves bullet-hell games, he started(!!!) one for the Community Project Monkey Touch:
http://www.monkey-x.com/Community/posts.php?topic=7479&app_id=231
(It takes a bit to load...scroll down for DanMonkey)

http://code.google.com/p/monkey-touch/


Sensei(Posted 2014) [#7]
Guys, this is fantastic thanks!
@Gerry, this is pretty much exactly what I want to do with the "regular" enemies, and @therevills, that is EXACTLY what I want to do with bosses.
Killed two birds with one stone there, thanks a mil!

I'll have a look at Samah's one tonight and hopefully be implementing your awesome suggestions over this weekend.
At the moment, my enemy class receives parameters such as X movement and Y movement in floats, so they're pretty basic right now where they have a start x/y and a move x/y. Adding the above suggestions will add loads of awesome movement patterns over the regular straight movement of the current system.
The boss class will use @therevills waypoint system, so thanks guys!

PS. This is why the Monkey community rocks! Almost always is there someone that can help/suggest useful information.


Paul - Taiphoz(Posted 2014) [#8]
What I did for Terminal 2 is a flight system that uses a data passing node system, a path would have x number of nodes(waypoints) each node would also have a varied set of attributes and as an enemy or unit flew along the path and reached a node the node would then pass new data to the unit, things like speed, turn rate, next node and fire patterns get passed, this allows me to easily map out a path and then edit the nodes to add fire patterns.

There are tons of ways you can go about this tho.


Sensei(Posted 2014) [#9]
@Slotman and @Gerry: implemented your suggestions and they work a treat thanks!
Next step is to implement @therevills' waypoint idea for a main boss.
Until then though, I need to first do more attack waves before the boss class can be done and tested :)
Again, thanks guys!


consty(Posted 2014) [#10]
This problem bothered me the previous week so today I have made a prototype. It would be a good place to start studying and experimenting.

Strict
Import mojo

Class EnumWaveStyle
	Const Straight:Int = 0
	Const Zigzag:Int = 1
	'Other wave styles for extension:
	'I now lazy to add more implementations
	'Waypoint (i.e. follow waypoints)
	'Boss (i.e. not going away until is dead)
End

Class Wave
	Field name:String				' for debugging purposes
	Field enemies:List<Enemy>		' a list of all the enemy objects
	Field finished:Bool = False		' quick way to determine if the wave is to be deleted
	Field waveStyle:Int				' the preferred style of this wave
		
	Method New()
		enemies = New List<Enemy>
		
		' the position of the wave
		Local position:Float = Rnd(0, DeviceWidth())

		' create 10 enemies (hardcoded)
		For Local i:Int = 0 To 10
			Local e:Enemy = New Enemy
			e.x = position ' random x position of the wave
			e.y = -(i * 60) ' distance between enemies is 60
			enemies.AddLast(e)
		Next
		
		' determine the style of the wave
		waveStyle = Int(Floor(Rnd(0.0, 2.0)))
	End
	
	Method Update:Void()
		' a simple variable used only in the zigzag effect trick
		Local counter:Int = 0
	
		For Local e:Enemy = Eachin enemies
			e.Update()
			
			' quicky way to move enemies based on their style
			' very ugly way, i hope I will find better examples :)
			If waveStyle = EnumWaveStyle.Zigzag
				Local phase:Float = counter*45
				Local magnitude:Float = 5
				Local speed:Float = 0.25
				e.xs = Sin((Millisecs() + phase)*speed) * magnitude
			End
			
			' quicky way to determine if wave is finished
			' that means that if all enemies are out of the
			' screen bounds only then entire wave is going extinct
			If e.y <= DeviceHeight()
				finished = False
			Else
				finished = True
			End
			
			counter += 1
		Next
	End
	Method Render:Void()
		For Local e:Enemy = Eachin enemies
			e.Render()
		Next
	End
End

' Very simple enemy class
Class Enemy
	Field x:Float
	Field y:Float
	Field xs:Float
	Field ys:Float
	Method New()
		ys = 2.25
	End
	Method Update:Void()
		x += xs
		y += ys
	End
	Method Render:Void()
		DrawOval(x-5, y-5, 10, 10)
	End
End

' very simple stopwatch implementation
Class Stopwatch
	Field Interval:Float
	Field Elapsed:Float
	Method New()
		Interval = 1
	End
	Method Tick:Bool()
		Local currentTime:Float = Millisecs() / 1000
		If currentTime - Elapsed >= Interval
			Elapsed = currentTime
			Return True
		End
		Return False
	End
End

Class Game Extends App
	Field waves:List<Wave>
	Field watch:Stopwatch

	Method OnCreate:Int()
		SetUpdateRate(60)
		Seed = Millisecs()

		' this is a timer to spawn waves
		' and that means in every 5 seconds
		' a new wave will be added
		watch = New Stopwatch
		watch.Interval = 5
		
		' create the list object but
		' do not add any waves yet
		' this will be done based on timing		
		waves = New List<Wave>
			
		Return 0
	End

	Method OnUpdate:Int()
		' when the timer reaches the required
		' interval then a new wave will be added
		If watch.Tick() Then
			Local w:Wave = New Wave
			' for debugging purposes a name is given this is though optional
			w.name = "Wave"+Int(watch.Elapsed)
			Print("Spawned wave: " + w.name)
			waves.AddLast(w)
		End
		
		' if there are any waves in the list
		' they are going to be updated
		If waves.Count() > 0
			For Local w:Wave = Eachin waves
				w.Update()
				' when a wave is finished it means
				' is not needed anymore and is going to be removed
				If w.finished
					Print("Removed wave: " + w.name)
					waves.RemoveEach(w)
				End
			Next
		End
		
		Return 0
	End

	Method OnRender:Int()
		Cls
		' the rendering of the waves
		If waves.Count() > 0
			For Local w:Wave = Eachin waves
				w.Render()
			Next
		End
		Return 0
	End
End

Function Main:Int()
	Local game:Game = New Game
	Return 0
End