Enemy attack patterns
Monkey Forums/Monkey Programming/Enemy attack patterns| 
 | ||
| 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? :) | 
| 
 | ||
| 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. | 
| 
 | ||
|  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) | 
| 
 | ||
| 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. | 
| 
 | ||
| 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. | 
| 
 | ||
| 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/ | 
| 
 | ||
| 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. | 
| 
 | ||
| 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. | 
| 
 | ||
| @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! | 
| 
 | ||
| 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
 |