Simple spaceship AI ideas for beginner???

BlitzMax Forums/BlitzMax Beginners Area/Simple spaceship AI ideas for beginner???

Zacho(Posted 2011) [#1]
At the current moment I have 10 different spaceships spawn at a random x value (0,700) and random y value (0,100) and the spaceships move right and left depending on the player's position. The cpu's chase the player down. This won't be effective as it will make the game very hard very quickly; any ideas on how to have "cool" enemy ai? I was thinking the computer float around in some random direction but I don't know how that can work without a timer?? (right? you need a timer for that)


Nate the Great(Posted 2011) [#2]
Well you could have some that ignore the player but have some special ability like shooting in all directions at once.. or some drones that only move in a straight line or some enemies that zig zag toward or spiral around the player or even super smart enemies that anticipate bullets and dodge them

if you really wanna get into advanced stuff try some genetic algorithms and neural networks :D

Last edited 2011


Zacho(Posted 2011) [#3]
Do you know of any things that are simple to program? like moving in random directions and switching direction after 2 seconds? how would I implement that? do i have to use a timer and do rand direction (n,ne,e,se,s,sw,w,nw)??


Nate the Great(Posted 2011) [#4]
well Im not sure exactly what you mean. I'm not sure what kind of game you are making exactly but generally you would use vectors like (1 , 1) and (-3.4 , 4.29) these would tell the ship how far to move in the x and y directions each frame. Then you could use timers to make enemies switch directions etc etc...


Zacho(Posted 2011) [#5]
Have you heard of a space shooter called invaderz? it was in the game programming for teens book for blitz basic written by maneeth seeth. I am thinking of putting a # of cpu's spaceships on the top half of the screen just floating about, no definite sense of direction. After a set period of time they would switch direction, like instead of floating nw they would float e for 2 sec (ex). is this beginner-able?


Nate the Great(Posted 2011) [#6]
Yeah definitely, I learned blitz basic from that book :D but im pretty sure it has the full source code available. maybe you could have a look at that if you wanted enemies similar to that?


Zacho(Posted 2011) [#7]
I loaned the book to a friend and I don't know when I will get it back, I will ask however.


AdamRedwoods(Posted 2011) [#8]
For "random" AI, I say giving different personalities to different ufo's is the way to go.

Also read the game design of Pacman, this is what they did for each of the ghosts and it is still relevant.
http://home.comcast.net/~jpittman2/pacman/pacmandossier.html#Chapter_3

What I do is I use vectors, as mentioned above:
Say X, Y is the location of your ufo:
x = x + DirX *speed
y = y + DirY * speed

The value for DirX or DirY is 1 or -1 or even 0.
To randomize the motion, choose one of those numbers:
Int(Rnd()*2-1)
And then use a hold counter for say 0.5 to 2 seconds to hold movement in that direction.

(More technical: the diagonals (dirx= +/-1, diry= +/-1) will actually speed up using this method so either perform a check and decrease the speed or setup a lookup table... TMI perhaps)

There are many, many ways to design AI and enemy motion.


Zacho(Posted 2011) [#9]
I am working on a way to set up a timer but I am having trouble. I am still trying though


col(Posted 2011) [#10]
You say you'd like something simple to use as AI.

In a game of this type I suggest to make the AI similar to this :-

Make the enemies go for the player but looking at a variable distance from the player (either to the side or infront, behind, you decide and you can random this factor ), giving them a chance to move out of the way and give more time for a reaction. As the game progresses decrease the 'range' around the player that the aliens will target to make it more difficult. Also enemy speed of movement can be used as a factor.

Its simple to implement, allowing for controllable variances for different enemies and when done correctly it's very effective.

As already mentioned.... Pacman used a similar setup and look how successful that is :D

Cheers


col(Posted 2011) [#11]
For a timer you can use something like :-

Record the current time using 'Global StartTime:int = Millisecs()'
Then in your 'main loop' use another variable to record the current time and check if the current time - the StartTime has gone passed a value that you'd like to use, remember that the 'Millisecs()' function counts in 1000s per second. So if you want the alien ships to change direction every second then you'd check if the current time variable minus the start time variable is greater than 1000, if so then run any code to change the direction then set the start time variable to the current time variable and start again.

A quick lowdown example
SuperStrict

Global StartTime:Int = MilliSecs()

'MainLoop
While Not KeyDown( KEY_ESCAPE )
	Local CurrTime:Int = MilliSecs()
	
	If CurrTime - StartTime > 1000
		Print "Swap direction"
		StartTime = CurrTime
	EndIf
Wend
End


This code will print 'Swap direction" every one second.

Best of luck with this.

Last edited 2011


Zacho(Posted 2011) [#12]
AI code
'***********
'This function regulates and maintains AI
'***********
Function AI () '[3.f]

Local CurrTime:Int = MilliSecs()
Local FireTime:Int = MilliSecs() - 100

DrawText"FireTime" + FireTime,300,10
DrawText"Equa" + (FireTime - StartTime),300,20
	
	If CurrTime - StartTime > 150
		'Print "Swap direction"
		For Local cpu:spaceship = EachIn cpuList
			cpu.move()
			StartTime = CurrTime
		Next 
	EndIf



If FireTime - StartTime > 48
		'If KeyHit(SPACEBAR)
		
		'***********
		'For every spaceship
		'***********
		For Local cpu:spaceship = EachIn cpuList
			
			'***********
			'Create a new instance of a computer bullet (Cbullet) using the "bullettype" as it's type
			'***********
			Local Cbullet:bullettype = New bullettype
				
				'***********
				'The computer bullet will be created at:
				'	cpu.x + 17
				'   cpu.y + 27
				'  with it's frame beginning at 0
				'***********
				Cbullet.x = cpu.x + 17
				Cbullet.y = cpu.y + 27
				Cbullet.frame = 0
			
			'***********
			'Add it to the CbulletList
			'***********
			ListAddLast(CbulletList,Cbullet)
			
					 	
		Next 
		
EndIf

EndFunction 


Spaceship AI type
Type spaceship
	Field x:Int,y:Int,frame:Int
	Field health:Int = 1, shield:Int
	
	Field xv:Int,yv:Int
		Method move ()'computer move
			xv = Rand(-2,2)
			yv = Rand(-2,2)
			
				x = x + xv * cpuspeed
				y = y + yv * cpuspeed
		EndMethod 
EndType 


Somewhat works but I am looking at understanding the timers more, and somehow making my AI not jittery


Zacho(Posted 2011) [#13]
Is it possible that I can do a + or minus operator?

like ie

x = x +/- xv * cpuspeed
y = y +/- yv * cpuspeed


Zacho(Posted 2011) [#14]
Nevermind about the + or minus operator, I fixed that part of my code. Another question, how can I randomize AI movement/firing? all of them update at the same time and I want to randomize this


Jesse(Posted 2011) [#15]
Col showed you a solution that would work good for the AI movement for each of the aliens as well as for shooting.

all you would have to do is to change the global variable StartTIme to a field field variable in the spaceship typ, the one thousand to a field variable that would hold a random minimum number to a max number.

something like this:
field BulletStartTime:double
field shootWaitTime:double


then a method in the spaceship type:
method shoot()
	local currentTIme:double = millisecs()
	If CurrentTime - shootStartTime > shootWaitTime
		
               '[ shoot code goes here]
		
                shootStartTime = CurrentTime
                shootWaitTIme = rand(100,500)
	EndIf
end method


then when you create your aliens you would add this extra code:
[...]
spaceship.shootStartTime = millisecs()
spaceship.shootWaitTime = rand(100,500) 


then when you call it it will fire on if the conditions are true:
spaceship.shoot()


the example is just for shooting but the same principle applies for movement.

the biggest obstacle you are facing now is not think in terms of objects. it's the object that does the shooting, it's the object that does the moving so treat accordingly.

Last edited 2011

Last edited 2011

Last edited 2011


Zacho(Posted 2011) [#16]
I am sorry, I am asking too much and not doing the work myself... I actually fixed my extremely jittery movement code by moving the timer's around a bit.

Just let me ask a question before I re-examine my code. A global timer using Millisecs () begins once the game begins correct? Once you call another variable to Millisecs () (say, in a function), it isn't the same time, why is that? Does the Millisecs () value depend on when it is called?


col(Posted 2011) [#17]
Hiya Zacho.

Relax... you're not asking too many questions at all. We're only too glad to help a fellow budding programmer and advise you in any way possible.

Inside your pc there is a timer ticking away every 1000th of a second. Using Millisecs() is just retrieving its current value. It ticks away whether you retrieve it or not. Once you get around getting the concept of storing its current value to give an initial time, then keep retrieving the current time again, test if the current time MINUS the start time is a certain value ( this 'certain value' is the wait time ), then it'll be easy for you. There's no need to worry what the actual value is, just compare a 'newer value' against an 'older value' to get a time difference in milliseconds.

My example was just a 'concept and logic' example, showing the logic of getting the current time and storing it, then checking the time again minus the value stored the first time we checked it to see how much time has passed, if the passed time is more than 1000 milliseconds which is 1 second, then do something. When you have 'done something' then store the current time again in the same variable. The process then continues in a loop.

You can use Millisecs() and store it as many times as you want, it doesn't matter. It doesnt affect this internal timer at all, remember all you are doing is just getting the value. The timer is still updating now while you are reading this.

The idea that Jesse is explaining above is...

You want the ships to move and fire at different times to each other, independently. This means that each ship will need its own timer, and the best most logical place to store the timers is in the 'Ship type' code as Jesse shows above. Your ship type would look something like this :

Type spaceship
	Field x:Int,y:Int,frame:Int
	Field health:Int = 1, shield:Int
	
	''''''''''ADDED
	Field BulletStartTime:Double
	Field shootWaitTime:Double
	'''''''''''''''
	
	Field xv:Int,yv:Int
	
	Method move ()'computer move
		xv = Rand(-2,2)
		yv = Rand(-2,2)
			
			x = x + xv * cpuspeed
			y = y + yv * cpuspeed
	EndMethod
	
	''''''''''ADDED
	Method shoot()
		Local CurrTime:Double = MilliSecs()
		If CurrTime - BulletStartTime > shootWaitTime
		
      	'[ shoot code goes here]
			shootStartTime = CurrentTime
         shootWaitTIme = Rand(100,500)
		EndIf
	End Method
	'''''''''''''''
EndType


Then in your main code, where you initialize and 'create' the aliens, you may have something along the lines of ( there are many many different ways to do this next part, its up to you how you do it in your code )

Global NumOfAliens:Int = 10
Global AlienShips:spaceship[ NumOfAliens ]

For i:Int = 0 Until NumOfAliens
	AlienShips[ i ] = New spaceship
	
	AlienShips[ i ].BulletStartTime = MilliSecs()
	AlienShips[ i ].shootwaitTime = Rand( 100,500 )
Next


Then in your main game loop you can use
For i:Int = 0 Until NumOfAliens
	AlienShips[ i ].shoot()
Next


This will call the 'shoot' Method for all of the spacehips in the AlienShip array, and because of the timer logic in that method, they will only shoot when 'CurrTime - BulletStartTime > shootWaitTime'. Remember that shootWaitTime is a random number.

To get the ships to move randomly, you would use another timer using the similar logic, but applied to the movement code, again store these in the 'SpaceShip' type so each ship has a different movement, then the 'Move' method to check the current time againt the wait time before moving and/or changing direction. You can have as many 'timers' as you want to do as many different things.

You will probably be 'tweaking' the timers A LOT to get the correct feeling that you're looking for in the game :D

I haven't tested the code above, but we're just trying to help you grasp the concept.

Have fun and chill out :D

[ edited for grammar ]

Last edited 2011


.rIKmAN.(Posted 2011) [#18]
A little OT, but I just wanted to thank AdamRedwoods for that Pacman AI link, I'd never seen it before and thought it was really interesting, so thanks! :)