360 shooter.... scrolling background

BlitzMax Forums/BlitzMax Beginners Area/360 shooter.... scrolling background

Yahfree(Posted 2008) [#1]
I want to get a seemless image that I can create a 'endless' feel to the background

2 questions on this:

1. Is there any easy way to make a image seemless in all 4 directions? Any freewere programs out there?

2. The obvious way to do this would be to lock the player in place while instead, moving the background and objects in the oposite direction. But how would you detect when to draw another background image(when the end of the first one enters view) and where would you draw it?

The image would probably be 1600 x 1200 (double the size of the 800x600 screen)

Thanks for any help!


tonyg(Posted 2008) [#2]
Gimp has a MakeSeamless function.
Texture Studio 1.14 might be what you're looking for.


ImaginaryHuman(Posted 2008) [#3]
It depends on the size of your background image compared to the size of the screen. If your screen resolution is the exact same size as your seamless image, or is smaller than your seamless image but no less than half its size, then you need to draw your seamless image four times. You just draw it in a grid of 2x2. ie four images in two rows of two.

Now to do the scrolling you'll need to think about how big your game world will be. If your game world is less or equal to twice the width or height of the seamless image then it's easy - you just use SetOrigin for scrolling and draw your seamless image at 0,0 and 0,ScreenHeight and ScreenWidth,0 and ScreenWidth,ScreenHeight.

But if you want your game world to be bigger than twice the size of the seamless texture then you need to now implement two For loops (nested) to draw a grid of seamless images. You'll also then need to use WorldX Mod TextureWidth to find the coordinate at which to start drawing horizontally, and WorldY Mod TextureHeight to find the coordinate at which to start drawing vertically. Then you need to either keep a counter of your horizontal/vertical position so that you keep drawing another image until you get PAST the edge of the screen, or know how many textures fit into the screen size and only do that many loops to draw the grid. You may need to then use modulo's on the SetOrigin too. Otherwise you could omit all the Mod's and just use SetOrigin with absolute world coordinates and figure out which coords to use for drawing.


JazzieB(Posted 2008) [#4]
You just need to use TileImage at co-ordinates based on your player's position. For example, just use something like TileImage imgBackground,-playerX,-playerY.

The only consideration for size is whether your target market/specification can support images larger than the screen - if you're using them, that is.


Yahfree(Posted 2008) [#5]
Thanks for the replies, and the link to the seemless texture generator.

I'll try some of these suggestions.


Yahfree(Posted 2008) [#6]
Jazzie's method works well, here's an example:


SuperStrict

Graphics 800,600

Local img:TImage = LoadImage("bg.png")
Local player:TImage = LoadImage("player.png")

Local px:Int = 380, py:Int = 280



While Not KeyHit(KEY_ESCAPE)
	Cls
	TileImage img,-px,-py
	
	If KeyDown(KEY_UP) py:-3
	If KeyDown(KEY_DOWN) py:+3
	If KeyDown(KEY_LEFT) px:-3
	If KeyDown(KEY_RIGHT) px:+3
	
	DrawImage player,380,280
	Flip 1
Wend
End


and the images:


bg.png


player.png



therevills(Posted 2008) [#7]
Now to guess the next question... rotation of the player ;-)


SuperStrict

Graphics 800,600,0

AutoMidHandle 1

Local img:TImage = LoadImage("bg.png")
Local player:TImage = LoadImage("player.png")

Local px:Float = 380, py:Float = 280
Local pdx:Float, pdy:Float
Local protation:Float
Local pspeed:Float = 0


While Not KeyHit(KEY_ESCAPE)
	Cls
	TileImage img,-px,-py
	
	If KeyDown(KEY_UP)	
		pspeed:+0.1
	End If
	
	If KeyDown(KEY_DOWN)	
		pspeed:-0.1
	End If

		
	If KeyDown(KEY_LEFT)
		protation:-1
	End If
	
	If KeyDown(KEY_RIGHT)
		protation:+1	
	End If


	pdx=Sin(protation)*pspeed
	pdy=-Cos(protation)*pspeed

	px :+ pdx
	py :+ pdy	


	SetRotation protation
	DrawImage player,380,280
	SetRotation 0
	Flip 1
Wend
End





Yahfree(Posted 2008) [#8]
Bah, I've made like 10 asteroids clones, I figured that one out a while ago :)


Yahfree(Posted 2008) [#9]
And here's some more "Space" like movement with a neat effect(layers of tiles moving different speeds with different alphas):

SuperStrict

Graphics 800,600,0
SetBlend ALPHABLEND


Local img:TImage = LoadImage("bg.png")
AutoMidHandle True
Local player:TImage = LoadImage("player.png")
AutoMidHandle False

Local px:Float = 400, py:Float = 300
Local pdx:Float, pdy:Float
Local protation:Float
Const ACCELERATION:Float = 0.1


While Not KeyHit(KEY_ESCAPE)
	Cls
	TileImage img,-(px/4),-(py/4)
	SetAlpha .7
	TileImage img,-(px/2),-(py/2)
	SetAlpha .4
	TileImage img,-px,-py
	SetAlpha 1
	
	If KeyDown(KEY_UP)	
		pdx:+Sin(protation)*ACCELERATION
		pdy:+-Cos(protation)*ACCELERATION
	End If
		
	If KeyDown(KEY_LEFT)
		protation:-4
	End If
	
	If KeyDown(KEY_RIGHT)
		protation:+4	
	End If


	px :+ pdx
	py :+ pdy	


	SetRotation protation
	DrawImage player,400,300
	SetRotation 0
	Flip 1
Wend
End


Now for a question:

In gameplay I want enemys chasing down the player, is there an easy way to do this?
My shot in the dark would be to compare the px/py to the enemy's x/y, and try to find a path.

How would you find the angle (for later use of dx and dy) between 2 points?


Ryan Burnside(Posted 2008) [#10]
Here are two functions




Also if you first find the angle you can move towards that target using the following formula:

x:+cos(angle)*step_size
y:+sin(angle)*step_size


Yahfree(Posted 2008) [#11]
Thanks for the segment -> angle function, thats what i'm looking for, I'll see what I can do


Yahfree(Posted 2008) [#12]
What about if you want the enemy's to orbit you? More cos/sin hattery?


therevills(Posted 2008) [#13]
Hows about this:

SuperStrict

Graphics 800,600,0
SetBlend ALPHABLEND
SeedRnd MilliSecs()


Global img:TImage = LoadImage("bg.png")
AutoMidHandle True
Global playerImg:TImage = LoadImage("player.png")
Global alienImg:TImage = LoadImage("player.png")
AutoMidHandle False


Global player:TPlayer = New TPlayer
player.image = playerImg
player.cx = 400
player.cy = 300

Global alien:TAlien = New TAlien
alien.image = alienImg
alien.x = Rand (0,800)
alien.y = Rand (0,600)
alien.acceleration = 0.3


While Not KeyHit(KEY_ESCAPE)
	drawBackground()
	player.update()
	alien.update()
	player.draw()
	alien.draw()	
	Flip 1
Wend

End

Type TEntity
	Field x:Float, y:Float
	Field dx:Float, dy:Float
	Field rotation:Float
	Field acceleration:Float = 0
	Field image:TImage	
End Type

Type TPlayer Extends TEntity		
	Field cx:Float, cy:Float
	
	Const ACCELERATION:Float = 0.1

	
	Method draw()
		SetRotation rotation
		DrawImage image,cx,cy
		SetRotation 0		
	End Method
	
	Method controls()
		If KeyDown(KEY_UP)	
			dx:+Sin(rotation)*ACCELERATION
			dy:+-Cos(rotation)*ACCELERATION
		End If

		If KeyDown(KEY_DOWN)	
			dx:-Sin(rotation)*ACCELERATION
			dy:+Cos(rotation)*ACCELERATION
		End If		
			
		If KeyDown(KEY_LEFT)
			rotation:-4
		End If
		
		If KeyDown(KEY_RIGHT)
			rotation:+4	
		End If		
	End Method

	
	Method update()
		controls()
		
		x :+ dx
		y :+ dy			
	End Method
End Type

Type TAlien Extends TEntity
	Field n:Int 

	Method draw()
		SetRotation rotation
		DrawImage image,x,y
		SetRotation 0
	End Method
	
	Method trackPlayer()
		Local radius:Float = 100
		
		dx = (player.cx - x) 
		dy = (player.cy - y) 
		Local dist:Float = Sqr(dx * dx + dy * dy) 
		
		If dist >= radius			
			dx:/dist * acceleration 
			dy:/dist * acceleration 				
			n = rotation + 90
		Else
			dx = dx+Cos(n)*(radius - 2)			
			dy = dy+Sin(n)*(radius - 2)			
			n :+1			
		EndIf
		rotation = point_direction#(x,y,player.cx,player.cy)
	End Method

	Method update()
		trackPlayer()
		x :+ dx -player.dx
		y :+ dy -player.dy				
	End Method
	
End Type

Function point_direction#(x1#,y1#,x2#,y2#)
	Local direction#= ATan2(y1-y2,x1-x2)+180

	While direction > 360
		direction:-180
	Wend

	While direction<0
		direction:+180
	Wend

	Return direction + 90

EndFunction


Function drawBackground()
	TileImage img,-(player.x/4),-(player.y/4)
	SetAlpha .7
	TileImage img,-(player.x/2),-(player.y/2)
	SetAlpha .4
	TileImage img,-player.x,-player.y
	SetAlpha 1
End Function


Its not great, but its a start...


Yahfree(Posted 2008) [#14]
Hehe, you didnt need to draw up a whole program, I just needed the tracking/orbiting code if to close, (I already have the game under developement), thanks though, i'll see what I can do with it


therevills(Posted 2008) [#15]
Hehe, you didnt need to draw up a whole program


LOL... I needed a break from my own game and it was fun - I havent programmed a 360 shooter before - havent even done an Asteroids clone.

thanks though


No problem


Yahfree(Posted 2008) [#16]
Alright, this is making him chase just fine, but when he orbits he circles the player alright but he violently shakes back and forth... why?


		If PointsToDistance(x,y,400,300) > 70 'chase
			angle = PointsToAngle(x,y,400,300)+90
			dx = AngleToDX(angle)*SPEED
			dy = AngleToDY(angle)*SPEED
		Else 'orbit
			dx:+Cos(orbit)*(70 - 2)			
			dy:+-Sin(orbit)*(70 - 2)
			orbit:+4
		End If



therevills(Posted 2008) [#17]
Your enemy must be going outside the radius, try changing the -2 to something greater.

Also I found that I needed to set orbit in the chase bit too:

If dist >= radius			
	dx:/dist * acceleration
	dy:/dist * acceleration
	orbit = rotation + 90
Else
	dx = dx+Cos(n)*(radius - 2)
	dy = dy+Sin(n)*(radius - 2)
	orbit :+1		
EndIf



Yahfree(Posted 2008) [#18]
still not working properly... odd..

here's my whole tenemy...

Type TEnemy
	Field x:Float,y:Float
	Field dx:Float,dy:Float
	Field angle:Int
	Field shoottimer:Int
	
	
	Const SPEED:Int = 15
	Method Create:TEnemy()
		ListAddLast(EnemyList,Self)
		x = 50
		y = 50
	End Method
	
	Method Update()
		DrawText PointsToDistance(x,y,400,300),0,20
		If PointsToDistance(x,y,400,300) >= 100
			angle = PointsToAngle(x,y,400,300)+90
			dx = AngleToDX(angle)*SPEED
			dy = AngleToDY(angle)*SPEED
		Else
			angle:+1
			dx:+AngleToDX(angle) * 5
			dy:+AngleToDY(angle) * 5
		End If
		
		x:+dx
		y:+dy
		
		x:+ -pdx
		y:+ -pdy
			
		If shoottimer > 20
			PlaySound shoot_sound
			Local bul:TBullet = New TBullet.Create(x,y,angle)
			shoottimer = 0
		End If
	
		SetRotation angle
		DrawImage player_img,x,y
		SetRotation 0
		
		shoottimer:+1
	End Method

End Type



therevills(Posted 2008) [#19]
what are your methods/functions for:

PointsToDistance

PointsToAngle

AngleToDX

?


therevills(Posted 2008) [#20]
I guess the functions are:


Function AngleToDX:Float(angle:Float)
	Return Cos(angle)
End Function

Function AngleToDY:Float(angle:Float)
	Return 	Sin(angle)
End Function

Function PointsToDistance#(x1#,y1#,x2#,y2#)
	Return Sqr(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
End Function


Function PointsToAngle#(x1#,y1#,x2#,y2#)
	Local direction#= ATan2(y1-y2,x1-x2)+180

	While direction > 360
		direction:-180
	Wend

	While direction<0
		direction:+180
	Wend

	Return direction

EndFunction



Okay... so try this:

SuperStrict

Graphics 800,600,0
SetBlend ALPHABLEND
SeedRnd MilliSecs()


Global img:TImage = LoadImage("bg.png")
AutoMidHandle True
Global playerImg:TImage = LoadImage("player.png")
AutoMidHandle False


Global player:TPlayer = New TPlayer
player.image = playerImg
player.cx = 400
player.cy = 300

Global alien:TAlien = New TAlien
alien.image = playerImg
alien.x = Rand (0,800)
alien.y = Rand (0,600)
alien.acceleration = 0.3

Global en:TEnemy = New TEnemy
en.x = 50
en.y = 50


While Not KeyHit(KEY_ESCAPE)
	drawBackground()
	player.update()
	alien.update()
	en.update()
	player.draw()
	alien.draw()	
	Flip 1
Wend

End

Type TEntity
	Field x:Float, y:Float
	Field dx:Float, dy:Float
	Field rotation:Float
	Field acceleration:Float = 0
	Field image:TImage	
End Type

Type TPlayer Extends TEntity		
	Field cx:Float, cy:Float
	
	Const ACCELERATION:Float = 0.1

	
	Method draw()
		SetRotation rotation
		DrawImage image,cx,cy
		SetRotation 0		
	End Method
	
	Method controls()
		If KeyDown(KEY_UP)	
			dx:+Sin(rotation)*ACCELERATION
			dy:+-Cos(rotation)*ACCELERATION
		End If

		If KeyDown(KEY_DOWN)	
			dx:-Sin(rotation)*ACCELERATION
			dy:+Cos(rotation)*ACCELERATION
		End If		
			
		If KeyDown(KEY_LEFT)
			rotation:-4
		End If
		
		If KeyDown(KEY_RIGHT)
			rotation:+4	
		End If		
	End Method

	
	Method update()
		controls()
		
		x :+ dx
		y :+ dy			
	End Method
End Type

Type TAlien Extends TEntity
	Field n:Int 

	Method draw()
		SetRotation rotation
		SetColor 0,255,0
		DrawImage image,x,y
		SetColor 255,255,255		
		SetRotation 0
	End Method
	
	Method trackPlayer()
		Local radius:Float = 100
		
		dx = (player.cx - x) 
		dy = (player.cy - y) 
		Local dist:Float = Sqr(dx * dx + dy * dy) 
		
		If dist >= radius			
			dx:/dist * acceleration 
			dy:/dist * acceleration 				
			n = rotation + 90
		Else
			dx = dx+Cos(n)*(radius - 2)			
			dy = dy+Sin(n)*(radius - 2)			
			n :+1			
		EndIf
		rotation = point_direction#(x,y,player.cx,player.cy)
	End Method

	Method update()
		trackPlayer()
		x :+ dx -player.dx
		y :+ dy -player.dy				
	End Method
	
End Type



Type TEnemy
	Field x:Float,y:Float
	Field dx:Float,dy:Float
	Field angle:Int
	Field shoottimer:Int
	
	Field radius:Float = 100
	
	Const SPEED:Float = 5
	
	Method Create:TEnemy()
	'	ListAddLast(EnemyList,Self)
		x = 50
		y = 50
	End Method
	
	Method Update()
		DrawText PointsToDistance(x,y,400,300),0,20
		dx = (player.cx - x) 
		dy = (player.cy - y)
		Local dist:Float = Sqr(dx * dx + dy * dy)
		If PointsToDistance(x,y,400,300) >= radius
			angle = PointsToAngle(x,y,400,300)
			dx = AngleToDX(angle)*SPEED
			dy = AngleToDY(angle)*SPEED
			angle:+180
		Else
			angle:+4
			dx:+AngleToDX(angle) * (radius- 2)
			dy:+AngleToDY(angle) * (radius- 2)
		End If
		
		x:+dx
		y:+dy
		
		x:+ -player.dx

		y:+ -player.dy	
			
		If shoottimer > 20
	'		PlaySound shoot_sound
		'	Local bul:TBullet = New TBullet.Create(x,y,angle)
			shoottimer = 0
		End If
	
		SetRotation angle - 90
		SetColor 0,255,255
		DrawImage playerImg,x,y
		SetColor 255,255,255
		SetRotation 0
		
		shoottimer:+1
	End Method

End Type

Function AngleToDX:Float(angle:Float)
	Return Cos(angle)
End Function

Function AngleToDY:Float(angle:Float)
	Return 	Sin(angle)
End Function


Function point_direction#(x1#,y1#,x2#,y2#)
	Local direction#= ATan2(y1-y2,x1-x2)+180

	While direction > 360
		direction:-180
	Wend

	While direction<0
		direction:+180
	Wend

	Return direction + 90

EndFunction

Function PointsToDistance#(x1#,y1#,x2#,y2#)
	Return Sqr(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
End Function


Function PointsToAngle#(x1#,y1#,x2#,y2#)
	Local direction#= ATan2(y1-y2,x1-x2)+180

	While direction > 360
		direction:-180
	Wend

	While direction<0
		direction:+180
	Wend

	Return direction

EndFunction


Function drawBackground()
	TileImage img,-(player.x/4),-(player.y/4)
	SetAlpha .7
	TileImage img,-(player.x/2),-(player.y/2)
	SetAlpha .4
	TileImage img,-player.x,-player.y
	SetAlpha 1
End Function


Using the same images you supplied...

red = player
green = my alien
blue = your type

So your type is now:


Type TEnemy
	Field x:Float,y:Float
	Field dx:Float,dy:Float
	Field angle:Int
	Field shoottimer:Int
	
	Field radius:Float = 100
	
	Const SPEED:Float = 5
	
	Method Create:TEnemy()
		ListAddLast(EnemyList,Self)
		x = 50
		y = 50
	End Method
	
	Method Update()
		DrawText PointsToDistance(x,y,400,300),0,20
		dx = (player.cx - x) 
		dy = (player.cy - y)
		Local dist:Float = Sqr(dx * dx + dy * dy)
		If PointsToDistance(x,y,400,300) >= radius
			angle = PointsToAngle(x,y,400,300)
			dx = AngleToDX(angle)*SPEED
			dy = AngleToDY(angle)*SPEED
			angle:+180
		Else
			angle:+4
			dx:+AngleToDX(angle) * (radius- 2)
			dy:+AngleToDY(angle) * (radius- 2)
		End If
		
		x:+dx
		y:+dy
		
		x:+ -pdx
		y:+ -pdy	
			
		If shoottimer > 20
			PlaySound shoot_sound
			Local bul:TBullet = New TBullet.Create(x,y,angle)
			shoottimer = 0
		End If
	
		SetRotation angle - 90
		DrawImage player_img,x,y
		SetRotation 0
		
		shoottimer:+1
	End Method

End Type



You may have to do this in your bullet code:

Local bul:TBullet = New TBullet.Create(x,y,angle-180)



Yahfree(Posted 2008) [#21]
You were right with the functions except AngleToDY returns the oposite of that return.


Also tis would be very hard to implement as I don't have a player type. But i'll see what I can do.

here's my complete init.bmx:




Yahfree(Posted 2008) [#22]
also why is this so dog slow? (its not the particles)

reason why I ask is because I use a similar routine for astroids clones for checking if the bullet hit the asteriod...

It keeps droping the FPS, it steadly drops like 4 fps every 3 seconds.

this is under TBullet.update

		If a < .7
			If ImagesCollide(bullet_img, x, y, 0, player_img, 400, 300, 0)
				BulletList.Remove(Self)
				ParticleExplosion(x, y, playerpart, 10, 40,,True)
				ParticleExplosion(x, y, firepart2, 10, 40)
			End If
			
			For Local e:TEnemy = EachIn EnemyList
				If ImagesCollide(bullet_img, x, y, 0, player_img, e.x, e.y, 0)
					BulletList.Remove(Self)
					ParticleExplosion(e.x, e.y, playerpart, 10, 40,,True)
					ParticleExplosion(e.x, e.y, firepart2, 10, 40)
					EnemyList.Remove(e)
				End If
			Next
		End If



tonyg(Posted 2008) [#23]
How many bullets in your bullet list?
List.remove(object) will scan through everything in the list until it finds the one to remove.
With your checks and loops that might be a lot of checking.


therevills(Posted 2008) [#24]
except AngleToDY returns the oposite of that return


Do you mean this?:

Function AngleToDY:Float(angle:Float)
	Return 	-Sin(angle)
End Function


Also tis would be very hard to implement as I don't have a player type. But i'll see what I can do


Have you tried just replacing your code (TEnemy) with the code I posted (the "So your type is now" bit)?


Yahfree(Posted 2008) [#25]
> Have you tried....

Actually I just did that(I had to remove the player.cx/player.cy for 400/300 though) but it worked.

Anyways it seems to be constantly orbiting rather than to chase after it gets out of radius...

Heres the code:

	Method Update()
		DrawText PointsToDistance(x,y,400,300),0,20
		dx = (400 - x) 
		dy = (300 - y)
		Local dist:Float = Sqr(dx * dx + dy * dy)
		If PointsToDistance(x,y,400,300) >= radius
			angle = PointsToAngle(x,y,400,300)
			dx = AngleToDX(angle)*SPEED
			dy = AngleToDY(angle)*SPEED
			angle:+180
		Else
			angle:+4
			dx:+AngleToDX(angle) * (radius- 2)
			dy:+AngleToDY(angle) * (radius- 2)
		End If
		
		x:+dx
		y:+dy
		
		x:+ -pdx
		y:+ -pdy	
			
		If shoottimer > 20
			PlaySound shoot_sound
			Local bul:TBullet = New TBullet.Create(x,y,angle-90,2)
			shoottimer = 0
		End If
	
		SetRotation angle - 90
		DrawImage player_img,x,y
		SetRotation 0
		
		shoottimer:+1
	End Method



>How many bullets in your bullet list?
List.remove(object) will scan through everything in the list until it finds the one to remove.
With your checks and loops that might be a lot of checking.

I figured as much, I'm using a rects overlap function, and it's not lagging now, but the problem is, I'd like to figure out a rects dimensions based on its angle... So if its pointing up or down(the bullet) create a 7x15 rect for checking(the dimension of the image).

But since they go at all angles how would you make a rectanlge to cover the whole thing. like at 45 deg, make a 11x11 (or whatever it may be?) rect to cover the whole image.

You'd probably create the rect's dimensions when creating the bullet based on angle, and store it with the bullet type to be called on with a collision check (fastest way?) But how do you get those dimensions?

how would you do this?


therevills(Posted 2008) [#26]
I had to remove the player.cx/player.cy for 400/300 though


Sorry about that, thought I took out all my code...

Anyways it seems to be constantly orbiting rather than to chase after it gets out of radius...


Thats why I said it was a start... ;-) On mine it looks like its a magnet kind of effect and you need to go pretty fast to get them to chase again...


Yahfree(Posted 2008) [#27]
I see, well, it will do for now. Now I need to figure out the bullet collision AND try to make my particles stick to the background, my particle system is odd, but I think I can rewrite it to stick to the background.


Another thing, is when the player dies, I want him to spawn back at point one, but the problem is, the enemys stick to the screen. I want them to stay back where the death happened and have to fly back to the player.

How would you do this?


The r0nin(Posted 2008) [#28]
Another thing, is when the player dies, I want him to spawn back at point one, but the problem is, the enemys stick to the screen. I want them to stay back where the death happened and have to fly back to the player.


You'll need to keep track of the offset (the number of times the screen has scrolled, and by how much for x and y). Then you simply add that offset to anything you want to "stay in place" (putting most of them off-screen most likely). That way the player re-appears at your origin and the enemies have to fly back to him.


Yahfree(Posted 2008) [#29]
cool, i'll try that, What about the angle -> size of rectangle thing?


Yahfree(Posted 2008) [#30]
Odd, this is proving difficult,

Local angles:Int[] = [0,45,90,135,180]

Print "Angle   -   Width   -   Height"
For Local i:Int = 0 To 4
	Print angles[i]+"   -   "+(Sin(angles[i])*7+7)+"   -   "+(Cos(angles[i])*15)
Next

produces some random results.

This is what i'm trying to accomplish:

*Bullet image is 7x15
*The bullet type has a coll_w and a coll_h field

1. When a bullet is created I check it's angle
2. I then use some math to fill the coll_w and coll_h fields, I need to create a rectangular dimensions to fully cover the bullet image no matter what angle it's pointing to.
3. Use these dimensions to create a collision checking rectangle, and use as needed


See above for my progress, remember the bullet image's width is 7px, and it's height is 15px.


Yahfree(Posted 2008) [#31]
Eh, just checking on the center of the bullet will work for now.

New question:

How do I create a radar? (you know like a little green circle in the HUD that has a brighter green line go in circles around it and lights up little green dots that would be enemies)

I'm searching the code archives but cant find any radar code...


Yahfree(Posted 2008) [#32]
Ok, This is what I have so far on the radar, but it's waaaaay off.

1. The player dot is suppost to be centered
2. The Enemies arent suppost to go off the radar

But it's a good start, anyone know what i'm doing wrong?

	SetColor 0,150,0
	DrawOval 100,100,200,200
	SetColor 255,255,255
	For Local e:TEnemy = EachIn EnemyList
		RadPx = (e.x/8000)*200 + (100*2)
		RadPy = (e.y/8000)*200 + (100*2)
		Plot(RadPx,RadPy)
	Next
	RadPx = (px/8000)*200 + (100*2)
	RadPy = (py/8000)*200 + (100*2)
	DrawOval RadPx-5,RadPy-5,10,10



Arowx(Posted 2008) [#33]
Your not offsetting the enemies from the players central position..

' Some constants to control the radar

Const radarScale = 40 '8000/200
Const radarOffset = 200 '100*2
Const radarWidth = radarOffset*2

'Calculate radar position as an offset from the player

RadPx = ((e.x-px)/radarScale)
RadPy = ((e.y-py)/radarScale)

'ensure radar wraps around player - only use if game arena wraps around player 

RadPx = wrap(-radarOffset,radarOffset,RadPx)
RadPy = wrap(-radarOffset,radarOffset,RadPy)

'wrap function ensures radar image wraps around game arena

Function wrap(min,max,value)
 local width:int = max-min
  if value > max then 
    value:-width
  else if value < 0 then 
    value:+width
  endif
end function


Hope this helps


Yahfree(Posted 2008) [#34]
the wrap function doesnt return anything?


Yahfree(Posted 2008) [#35]
alright this is what I have now... getting close, but there's still a blob of dots running around on the screen, not vanishing when they get to the boundries of the radar...


here's the wrap function:

Function RadarWrap:Int(_Min:Float,_Max:Float,value:Float)
 Local width:Int = _Max-_Min
  If value > _Max Then 
    value:-width
  Else If value < 0 Then 
    value:+width
  EndIf

Return value
End Function

here's the constants(what's this offset thing?):
Const radarScale:Int = 40 '8000/200
Const radarOffset:Int = 50 'What's this?
Const radarWidth:Int = radarOffset*2

Here's the radar code:
	'Radar(replace w/ image later)
	SetColor 0,150,0
	DrawOval 824,568,200,200
	SetColor 255,255,255

	'plot a pixel at the enemies locations on the radar
	For Local e:TEnemy = EachIn EnemyList
		RadPx = ((e.x-px)/radarScale)
		RadPy = ((e.y-py)/radarScale)

		RadPx = RadarWrap(-radarOffset,radarOffset,RadPx) + 824 ' radar's x location
		RadPy = RadarWrap(-radarOffset,radarOffset,RadPy) + 568 ' radar's y location
		Plot(RadPx,RadPy)
	Next
	
	'draw a white oval at the center of the radar, this represents the player.
	DrawOval 919, 663, 5, 5



Arowx(Posted 2008) [#36]
Looks good,

Oops the radarOffset is the radius of the radar, radarRadius would indeed be a better name for the variable!

Regards


Yahfree(Posted 2008) [#37]
hmm, still doesnt explain why the dots travel around the screen


Arowx(Posted 2008) [#38]
Oops, well the Radar Offset should be 100 as your example radar has a width of 200.

And the wrap should be based < _Min not < 0

	Const radarScale:Int = 40 '8000/200
	Const radarOffset:Int = 100 'Radius of Radar
	Const radarWidth:Int = radarOffset*2

Function RadarWrap:Int(_Min:Float,_Max:Float,value:Float)
 Local width:Int = _Max-_Min
  If value > _Max Then 
    value:-width
  Else If value < _Min Then 
    value:+width
  EndIf

Return value
End Function


Then there is the fact that your actual game space does not seem to have a limit so maybe you should just have a min and max for the radar.

Or you could use a distorted radar where it displays the square or cube-root of the distance from the player?


Yahfree(Posted 2008) [#39]
Sorry for the late reply, but this still isn't working properly, I've tried a different approach:


Const radarScale:Int = 40 '8000/200
Const radarRadius:Int = 100 'Radius of Radar

Function PointsToDistance#(x1#,y1#,x2#,y2#)
	Return Sqr(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
End Function

	'Radar(replace w/ image later)
	SetColor 0,150,0
	DrawOval 824,568,200,200
	SetColor 255,255,255

	'plot a pixel at the enemies locations on the radar
	For Local e:TEnemy = EachIn EnemyList
		RadPx = ((e.x-px)/radarScale+(px/radarScale)) + 919
		RadPy = ((e.y-py)/radarScale+(py/radarScale)) + 663
		If PointsToDistance(919,663,RadPx,RadPy) < radarOffset
			Plot(RadPx,RadPy)
		End If
	Next
	
	'draw a white oval at the center of the radar, this represents the player.
	DrawOval 919, 663, 5, 5


When you first start the game it works perfectly, until you move the player, then the place where the dots close in on the big dot(the player) moves off a bit..


Digital Anime(Posted 2008) [#40]
I created the following code to handle positions easier with a function

here is the source of my zrm.bmx file I include in games in which I want to use rotate, shake or zoom everything drawn with the new functions

I draw tiles on an x and y position for example with the zrm drawcommands and let tell how many degrees all should be rotated, moved out of position or even in wich scale it should be drawn realtime.

I wonder if this is usefull for your task :

'########################################
'### Zoom Rotate And Move Version 1.0 ###
'########################################
'
' This file is used to zoom, rotate and move everything that you want by using the ZRM functions
' and can be implemented in your project even when you are almost done
'
' I needed only the rotate function at first to rotate all stuff 180 on the display, so I only need
' ZRM_Rotate (180) to determine how every ZRM draw function should be rotated
'
' DrawImage will be replaced by ZRM_DrawImage
'
' include this file in your Blitzmax application with :
' 
' include "ZRM.bmx"
'
' This needs to be done after the setgraphics command
'
' Functions :
'
' - ZRM_Zoom (x:Float, y:Float)                                : Zooms everything on the screen drawn with ZRM_Draw functions
'                                                                Is used the same as SetScale
'
' - ZRM_Rotate (angle:Float)                                   : Rotates everything on the screen drawn with ZRM_Draw functions
'                                                                Is used the same as SetRotation
'
' - ZRM_Move (x:Float, y:Float)                                : Moves everything from the middle of the screen drawn with ZRM_Draw functions
'                                                                X stands for - or + amount of pixels to go left or right
'                                                                Y stands for - or + amount of pixels to go up or down
'
' - ZRM_SetScale (x:Float, y:Float)                            : Replacement for SetScale
'
' - ZRM_SetRotation (angle:Float)                              : Replacement for SetRotation
' 
' - ZRM_DrawText (Text:String, x:Float, y:Float)               : Replacement for DrawText
'
' - ZRM_DrawImage (Image:TImage, x:Float, y:Float)             : Replacement for DrawImage (Works the same, but won't work with more frames)
'
' - ZRM_DrawRect (x:Float, y:Float, Width:Float, Heigth:Float) : Replacement for DrawRect
'
' - ZRM_DrawRect (x:Float, y:Float, Width:Float, Heigth:Float) : Replacement for DrawOval
'
' - ZRM_DrawLine (x1:Float, y1:Float, x2:Float, y2:Float)      : Replacement for DrawLine
'
' - More functions will be added
'
'Written by Mark Gerritsen

Global ZRM_Zoom_X:Float = 1
Global ZRM_Zoom_Y:Float = 1
Global ZRM_Rotate_Angle:Float = 0
Global ZRM_Move_X:Float = 0
Global ZRM_Move_Y:Float = 0
Global ZRM_SetScale_X:Float = 1
Global ZRM_SetScale_Y:Float = 1
Global ZRM_SetRotation_Angle:Float = 0
Global ZRM_Width:Int
Global ZRM_Height:Int
Global ZRM_Temp_X_X:Float
Global ZRM_Temp_X_Y:Float
Global ZRM_Temp_Y_X:Float
Global ZRM_Temp_Y_Y:Float

ZRM_Width  = GraphicsWidth()
ZRM_Height = GraphicsHeight()

Function ZRM_Zoom (X:Float, Y:Float)
	ZRM_Zoom_X = X
	ZRM_Zoom_Y = Y
End Function

Function ZRM_Rotate (Angle:Float)
	ZRM_Rotate_Angle = Angle
End Function

Function ZRM_Move (X:Float, Y:Float)
	ZRM_Move_X = X
	ZRM_Move_Y = Y
End Function

Function ZRM_SetScale (X:Float, Y:Float)
	ZRM_SetScale_X = X
	ZRM_SetScale_Y = Y
End Function

Function ZRM_SetRotation (Angle:Float)
	ZRM_SetRotation_Angle = Angle
End Function

Function ZRM_Drawtext (Text:String, X:Float, Y:Float)
		
	ZRM_Calculate (X, Y)
	DrawText Text, ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X), ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y)

End Function

Function ZRM_DrawImage (Image:TImage, X:Float, Y:Float)

	ZRM_Calculate (X, Y)
	DrawImage Image, ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X), ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y)

End Function

Function ZRM_DrawRect (X:Float, Y:Float, Width:Float, Height:Float)

	ZRM_Calculate (X, Y)
	DrawRect ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X), ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y), Width, Height

End Function

Function ZRM_DrawOval (X:Float, Y:Float, Width:Float, Height:Float)

	ZRM_Calculate (X, Y)
	DrawOval ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X), ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y), Width, Height

End Function 

Function ZRM_DrawLine (X1:Float, Y1:Float, X2:Float, Y2:Float)

	ZRM_Calculate (X1, Y1)
	Local X1_New:Float = ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X)
	Local Y1_New:Float = ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y)
	ZRM_Calculate (X2, Y2)
	Local X2_New:Float = ((ZRM_Width / 2) + ZRM_Temp_X_X - ZRM_Temp_X_Y + ZRM_Move_X)
	Local Y2_New:Float = ((ZRM_Height / 2) + ZRM_Temp_Y_X + ZRM_Temp_Y_Y + ZRM_Move_Y)
	SetScale (1, 1)
	SetRotation (0)
	DrawLine X1_New, Y1_New, X2_New, Y2_New 

End Function 

Function ZRM_Calculate(X:Float, Y:Float)

	SetRotation (ZRM_SetRotation_Angle + ZRM_Rotate_Angle)
	SetScale (ZRM_SetScale_X * ZRM_Zoom_X), (ZRM_SetScale_Y * ZRM_Zoom_Y)
	ZRM_Temp_X_X = ((Cos(ZRM_Rotate_Angle) * (X - (ZRM_Width / 2)) * (ZRM_Zoom_X)))
	ZRM_Temp_X_Y = ((Sin(ZRM_Rotate_Angle) * (Y - (ZRM_Height / 2)) * (ZRM_Zoom_Y)))
	ZRM_Temp_Y_X = ((Sin(ZRM_Rotate_Angle) * (X - (ZRM_Width / 2)) * (ZRM_Zoom_X)))
	ZRM_Temp_Y_Y = ((Cos(ZRM_Rotate_Angle) * (Y - (ZRM_Height / 2)) * (ZRM_Zoom_Y)))

End Function



Yahfree(Posted 2008) [#41]
thanks for sharing, however, I don't think this is what i'm looking for exactly.

Basicly:

My game level is infinite, the radar is based off of what is around the player for a 8000px radius, the plan is to plot a pixel on the radar if the enemy is within 8000px of the player.

This is what i'm having trouble with, any help appriciated!


Jesse(Posted 2008) [#42]
see if this gives you an idea



Yahfree(Posted 2008) [#43]
I got it, thanks for all the help, the problem was me not adding the center of the screen into account..