Community Project - Alien Breed game

Miscellaneous Forums/Blitz Showcase/Community Project - Alien Breed game

Currently Standing like this:



Included are:

Map editor - This needs to be extended however, it allows you to create maps.
Basic Engine - The Engine as it stands, basic collision detection, objects, and animated player.
Example Map - Um... example map.
Map Tile Set - Thanks to coffeedotbean for this
Player gfx - Again from Coffeedotbean
Object Tile set - I've created 2 objects so far, ammo and medikit


Let see what we can make of this, we need tile sets, maps, and of course a story and an engine.

The maps are 256x256 tiles in size with 32x32px tiles. They are made up of 4 layers:
Layer 0: Collision layer, either yes or no.
Layer 1: Base coat: The basic look of the level.
Layer 2: Objects: Pick up/ shoot etc.
Layer 3: Overlay : Drawn over the top of everything else to give a sense of depth.
Layer 4: Block Overlay : Like the overlay, however uses drawblock so there's no transparancy.

Things that need to be done:

[done] 1. Shooting... Give the player the ablity to shoot.
[done] 2. Doors... Add door objects that when the player touches them they open
[done] 3. Keys... Add a key object so that when the player has this object doors open
[done] 4. Player 2... Currently the engine will support multiple players as the player is a type, the map also averages the 2 positions and positions itself accordingly
[not needed in the end my screen averaging code did this for us!] 5. Push scroll... Instead of the player being fixed in the middle of the screen the player walks around in the centre section of the screen and when he reaches a boundry will push the scrolling. This is vital for the 2 player option.
[done 30%] 6. Bad Guys... Create a type for the bad guys much like the player type so bad guys can roam, spawn and attack
[done 30%]7. Bad Guy Ai... AI for the baddies, so they attack you!
[done]8. Ammo... Once firing is in ammo needs to be taken into account, also multiple weapons.
9. Credits... Add an object to give a player credits to buy things using the...
10. Intex Systems... Or whatever, the consoles to log on to get weapons/armour etc.


Once these 10 items are in I think we will have a game engine to write a game from. Once the engine is complete we can then get going with mapping and a scripting system to give each level a mission.



Come on guys... Support the community and add some code.

ah thats looking better now.

As soon as Im done with the code im working on now I will make a start on that list. I'm sure others will to.

I would stick it on the front page too, as lots of people seemed to miss the first community project `Jump Around` completely, myself included. And I regularly read the forums. Still not sure how I missed it to be honest.

Jason.

looking really nice... who did the gfx so far?

Just added locked doors and keys and added more media for keys and doors. Doors still need to be animated to open.

Bouncer, the player and bulk of the tile media is from CoffeedotBean's retired Alpha Breed project as mentioned in the first post.

I'm getting the feeling no-one is interested in this as I seem to be the only one coding this.

Discussion: Would it be better to have security clearance rather than keys? They'd still be certain keys for certain doors, however, if you had basic security clearance that opens a load of doors, then you'd find an ID card say to give you higher clearance level to get deeper into the map? I just think 1 key / 1 door seems a little primitive? Thoughts?

Here's the first version of the map editor..no lightmapping yet, but it does have a window for tile selector(That can be dragged etc. not the prettiest looking thing, but it's as functional as needed.)

Also, a cool feature that REALLY speeds up developement is, hold in tab and then push in the direction of the button you wanna go to. It'll instantly warp there. (It's accurate most of the times)

Has paste and fill tile modes.

Mouse wheel over tile selector scrolls. Lmb picks a tile. (And pastes if over map)

You can re-arrange tile order in the selector window by pressing RMB to switch tiles. Useful for grouping commonly used tiles together.

;For ;Top Down;
;
;
;Map and fx editor.
;
;Set up code by Rob Farley.
;
;Editor V2.0 Coded by Antony Wells.
;
;Open Source.

;-[setup by Rob farley.]
Include "M_Engine.bb"
Graphics 800,600,32,2
HidePointer
Global overBase.base,hitBase.base
Global tileW#=32,tileH#=32
Global maxtile = 190
Global tiles = LoadAnimImage("gfx/tiles.png",tileW,tileH,0,maxtile)
Global cursor = LoadImage("gfx/cursor.png")
MaskImage cursor,255,0,255
SetBuffer BackBuffer()
font = LoadFont("Arial.tff",15)
SetFont font
;-------------]
Global cTile.tile
genTiles()
Color 128,128,128
newButton( 10,540,60,20,"Load")
newButton( 80,540,60,20,"Save")
Color 255,0,0
newbutton( 150,540,60,20,"Clear")
;newButton( 220,540,60,20,"U
tileV.tile=First tile
viewY=300
ViewX=600
fromX=20
fromY=20
dragB.base=newButton(GraphicsWidth()/2-40,viewY-10,80,20,"Drag")
dragC.base=newButton(ViewX-20,viewY/2-20,40,40,"Pull")
dragA.base=newButton(20-10,20-10,20,10,"#")
dragD.base=newButton(fromX+viewX-10,fromY+viewY-10,20,20,"//")

Color 20,128,128
newText(GraphicsWidth()-100,5,"Edit Modes")
aMode.base=newText(GraphicsWidth()-150,40,"Mode:Paste")
pasteM.base=newButton(GraphicsWidth()-80,20,50,20,"Paste")
fillM.base=newButton(GraphicsWidth()-80,50,50,20,"Fill")


Global overTile.tile
;---

;---[ Map Specific] 
	;set up default blank map
	initMap(255,255)
;-

Repeat
	Cls:uiCycle();
	mx#=MouseX()
	my#=MouseY()
	
	If MouseHit(1)
		Select state
			Case 0
				If overTile<>Null cTile=overTile
		End Select
	EndIf
	If MouseHit(2)
		Select state
			Case 0
				If overTile<>Null
					If ctile<>Null
						tnTile.tile=Before cTile
						Insert cTile Before overTile
						Insert overTile After tnTile
					EndIf
					
				EndIf
				
		End Select
	EndIf
	
	mxs=MouseXSpeed()
	mys=MouseYSpeed()
	FlushMouse
	Select uiHit()
		Case "Paste"
			cMode=1
			rename(amode,"Mode:Paste")
		Case "Fill"
			cMode=2
			rename(amode,"Mode:Fill")
		Case "Drag"
			viewY=mY-fromY
		Case "Pull"
			viewX=mX-fromX
		Case "#"
			fromX=mx-viewX/2
			fromY=my
			dragA\x=mx+20
			dragA\y=my-10
		;	viewX=fromX
		Case "//"
			viewY=mY-fromY
			viewX=mX-fromX
		Default
			If MouseDown(3)
				If overTile<>Null
					If Not MouseDown(1)
						fromX=fromX+mxs
						fromY=fromY+mys
							dragA\Y=draga\y+mys
					Else
				
					viewX=viewX+mxs
					viewY=viewY+mys
					EndIf
				EndIf
				
			EndIf
			
	End Select
	FlushMouse 
	dragA\w=viewX
	draga\x=fromX
	dragD\x=viewX-10+fromX
	dragD\y=viewY-10+fromY
	dragB\y=viewY-10+fromY
	DragB\x=viewX/2-40+fromX
	dragC\x=viewX-20+fromX
	dragC\y=viewY/2-20+fromY
mz=MouseZSpeed()
If mz>0
	For mz=mz To 0 Step -1
	tileV=After tileV
	If tileV=Null tileV=First tile
	Next
Else If mz<0
	For mz=Abs(mz) To 0 Step -1
	tileV=Before tileV
	If tileV=Null tileV=Last tile
	Next
EndIf






	
	;-[ The following code contains the parts that actually edit the map)

	
	renderMap()
	dumpTiles(tileV,fromX,fromY,viewX,viewY)
	
	If cTile<>Null DrawImage cTile\id,MouseX(),MouseY()
	
	If Not ((mx>fromx And mx<(fromx+viewX) And my>fromY-10 And my<fromy+viewY) Or overBase<>Null Or hitBase<>Null)
		tileX=Int(mx)/Int(tileW)
		tileY=Int(my)/Int(tileH)
		Color 255,0,0
		Rect tileX*tileW,tiley*tileH,tileW,tileH,0
		If MouseDown(1)
			Select cMode
			Case 2
				fillTile(cTile,tileX,tileY)
				
			Default 
				pasteTile(cTile,tileX,tileY)
			End Select
			
		EndIf
		
	EndIf
	
		Color 255,255,255
;	Rect fromX,fromY+viewY,ViewX,4
;	Rect fromX+viewX,fromY,4,viewY
	Rect fromX,fromY,viewX,viewY,0	

	
	
	renderGui()
	
	
	;This lets you shift the mouse cursor to the closet button
	;in the direction the mouse is moving when you press TAB
	;This speeds up editing a lot.
	If KeyDown(15)
		cx#=Float(MouseX())+Float(mxs)*6
		cy#=Float(MouseY())+Float(mys)*6
			xb=Sgn(mxs)
		yb=Sgn(mys)
		cbase.base=Null
		sd#=999999
		If MilliSecs()>ws+500
		For b.base =Each base
			If b\is=ui_button And b<>overBase
				ix#=b\x+b\w/2
				iy#=b\y+b\h/2
				xd#=ix-cx
				yd#=iy-cy
				bx=Sgn(xd)
				by=Sgn(yd)
				
				If bx=xb And by=yb
				td#=Sqr(xd*xd+yd*yd)
				If td<sd 
					cbase.base=b
					sd=td
					ws=MilliSecs()
				EndIf
				EndIf
			EndIf
		Next
		If cbase<>Null
	
			lockX=cbase\x+cbase\w/2
			lockY=cbase\y+cbase\h/2
			DrawImage cursor,lockx,lockY
			Flip
			Repeat
				
			Until KeyDown(15)=0
			MoveMouse lockX,lockY
			FlushMouse 	
		
		EndIf
		
		
		EndIf
	EndIf
	DrawImage cursor,MouseX(),MouseY()
	;--
	Flip
Until KeyDown(1)



Function genTiles()	
	For j=0 To maxTile-1
		t.tile =New tile
		t\id=CreateImage(tileW,tileH)
		CopyRect 0,0,tileW,tileH,0,0,ImageBuffer(tiles,j),ImageBuffer(t\id)
		If imageEmpty(t\id)
			FreeImage t\id
			Delete t
		EndIf
		
	
	Next
End Function


Function dumpTiles(t.tile,x,y,maxWidth=250,maxHeight=250,smartDump=True,checkMouse=True)
	ox#=x
	oy#=y
	If t=Null t=First tile
	mx#=MouseX()
	my#=MouseY()
	Viewport x,y,maxWidth,maxHeight
	If checkMouse overTile=Null
	dispW=GraphicsWidth()
	dispH=GraphicsHeight()
	start.tile=t
	Repeat
		tc=tc+1
		DrawImage t\id,x,y
		If checkMouse
			If mx>x And mx<x+tileW
			If my>y And my<y+tileH
				overTile=t
			EndIf
			EndIf
		EndIf
		If t=cTile
			Color 255,255,255
			Rect x,y,tilew,tileh,0
		EndIf
		
		x=x+tileW
		If smartDump
			If x=>ox+maxWidth
				x=ox
				y=y+tileH
				If y=>oy+maxHeight-1 Exit ;y=0
			EndIf
		EndIf
		t=After t
		If t=Null t=First tile 
	Until t=start
	Viewport 0,0,GraphicsWidth(),GraphicsHeight()
	;DebugLog tc
End Function

Function uiCycle()
mx=MouseX()
my=MouseY()
Local but[3]
but[0]=MouseDown(1)
but[1]=MouseDown(2)
but[2]=MouseDown(3)

If but[0]=False hitBase=Null
overBase=Null
	For b.base=Each base
		If mx>b\x And mx<b\x+b\w
		If my>b\y And my<b\y+b\h
			overBase=b
			If but[0] 
				If hitbase=Null hitBase=overBase 
			EndIf
		EndIf
		EndIf
		
	Next	
	
End Function

Function uiHit$()
	If hitBase<>Null Return hitbase\id
End Function


Function uiOver$()
	If overBase<>Null Return overBase\id
End Function





;--- DO CUBIC LIGHTING FOR CRYO NEXT< YO
Function imageEmpty(image,imagePoint=5000,maskR=255,maskG=0,maskB=255,resetMask=True)

	SetBuffer ImageBuffer(image)
	LockBuffer
	iw=ImageWidth(tiles)
	ih=ImageHeight(tiles)
	For x=0 To ImageWidth(image)-1
	For y=0 To ImageHeight(image)-1
		rgb=ReadPixelFast(x,y)
		r#=(rgb Shr 16) And 255
		g#=(rgb Shr 8) And 255
		b#=(rgb And 255)
		If resetMask
			If r=maskR And b=maskB And g=MaskG
				WritePixelFast(x,y,0 Or (0 Shl 8) Or (0 Shl 16))
				r=0
				g=0
				b=0
			EndIf
		EndIf
		rd#=r-lr#
		gd#=g-lg#
		bd#=b-lb#
		shift#=shift+Sqr(rd*rd+gd*gd+bd*bd)
		lr#=r
		lg#=g
		lb#=b
	Next
	Next
	UnlockBuffer
	SetBuffer BackBuffer()
	If shift>imagePoint Return False
	Return True
End Function

;-SmallGUI ;just buttons for now, but will expand for the game it's self.

Type cache
	Field img
	Field x,y,width,height
End Type

Type base
	Field is
	Field x,y,w,h
	Field id$,r,g,b
End Type
Global doCache=0
Const ui_button=1,ui_text=2
Function newButton.base(x,y,w,h,title$)
	b.base= New base
	b\is=ui_button
	b\x=x
	b\y=y
	b\w=w
	b\h=h
	b\r=ColorRed()
	b\g=ColorGreen()
	b\b=ColorBlue()
	b\id=title
	doCache=True
	Return b
;	Return Handle(b)
End Function

Function newText.base(x,y,txt$)
	b.base=New base
	b\x=x
	b\y=y
	b\is=ui_text
	b\id=txt
	b\r=ColorRed()
	b\g=ColorGreen()
	b\b=ColorBlue()
	doCache=True
	Return b
End Function

Function rename(in.base,txt$)
	in\id=txt
End Function


Function renderGui()
	For b.base =Each base
		Select b\is
			Case ui_button
				
				Color 20,20,20
				Rect b\x+5,b\y+5,b\w,b\h,1
				
				If hitbase=b
					xm#=5
					ym#=5
				Else
					xm=0
					ym=0
				EndIf
				Color b\r,b\g,b\b
				Rect b\x+xm,b\y+ym,b\w,b\h
				Color 255,255,255
				Rect b\x+xm,b\y+ym,b\w-1,b\h-1,0
				Color 40,40,40
				Rect b\x+xm+1,b\y+ym+1,b\w-1,b\h-1,0
				Color 10,10,10
				Text b\x+xm+b\w/2,b\y+ym+b\h/2,b\id,True,True
				Color 255,255,255
				Text b\x+xm+b\w/2,b\y+ym+b\h/2-3,b\id,True,True
				
			Case ui_text
			
				Color 5,5,5
				Text b\x+4,b\y+4,b\id
				Color b\r,b\g,b\b
				Text b\x,b\y,b\id
				
		End Select
	Next
	
End Function

Function genCaches()
	sx#=9999
	sy#=9999
	bx#=-9999
	sy#=-9999
	For b.base =Each base
		x2#=b\x+b\w
		y2#=b\y+b\h
		If b\x<sx sx=b\x
		If b\y<sy sy =b\y
	Next
	
End Function



;Map Engine 2 (Or at least it will be. can't use the old 
;one as it won't be compatible with the lightmapping process)
;

Type tile
	Field id
End Type

Dim map.tile(0,0,0)
Global mapWidth,mapHeight,mapDepth
Global xoff#,yoff#,mapX#,mapY# ;mapx,y in tiles, xoff/yoff offset in pixels(Within range of 0 to tileWidth-1)
Global tileWidth,tileHeight




Function initMap(width,height,tileW2=32,tileH2=32,depth=4)
	Dim map.tile(width,height,depth)
	mapWidth=width
	mapHeight=height
	tileWidth=tileW2
	tileHeight=tileH2
	mapDepth=depth
End Function

Function pasteTile(tile.tile,x,y,layer=1)
	map(x,y,layer)=tile
End Function

Function fillTile(tile.tile,x,y,layer=1,smartFill=False)
    If smartFill
    Else
		For mx=0 To mapWidth-1
		For my=0 To mapHeight-1
			map(mx,my,layer)=tile
		Next
		Next
	EndIf
End Function

Function clearMap()
	Dim map.tile(mapWidth,mapHeight,mapDepth)
End Function

Function renderMap()

	tileHorz=GraphicsWidth()/tileWidth ;how many tiles we can see horizontally.
	tileVert=GraphicsHeight()/tileHeight ;vertically speaking, this is the same.
	For td=1 To mapDepth
	For tx=mapX To mapX+TileHorz
	For ty=mapY To mapY+tileVert
		tile.tile=map(tx,ty,td)
		If tile<>Null
			;End
			ax=tx*tileWidth
			ay=tY*tileHeight
			DrawImage tile\id,ax,ay
		EndIf
	Next
	Next
	Next
	
	
End Function




Antony,

I've updated the map format so there's an extra layer now, there's now a forth layer that uses drawblock instead of drawimage for solid overlay blocks.

Also the objects (layer 2) have a seperate set of tiles now.

How is the light mapping going to work? Does it create new tiles or what? Or does the whole map get created as a new image and it just scrolls around it? Just curious.

Any amount of layers will be cool with the above editor. Each unique Tile has it's own tile object.(Tiles on the map just reference the original)..so soon you'll be able to set a tile to 'collider/shadow caster etc'

The lightmapping works(and it's memory heavy, but considering this is a 2d game and most people have hundreds of mb, i'm not worried) by creatig a new tile for each visisble tile on the map, then it renders the light per-pixel across the surface, doing an intersection test of some sorts against the collider tiles. (it'll do this in the map editor, and save the results. Not in real time)

I was going to do a custom format with zlib compression, due to the amount of tiles it spews out..any code in your current version that rely's heavily on the format you're using now?

nice textures there

> I'm getting the feeling no-one is interested
> in this as I seem to be the only one coding this.

Give me a week and I'm gonna add multi-player support to Jump Around.

I was going to do a custom format with zlib compression, due to the amount of tiles it spews out..any code in your current version that rely's heavily on the format you're using now?
The object layer probably is the biggy as the content of the tile will change therefore the lightmapping wants to avoid this layer. And of course the collision, but I guess this is all fixable!

The door code looks at if you're colliding against a door object and if you are checks if you've got a key, if you do it removes object and collision data from the map file to allow you to pass.

Check out the new code and see what you think.

Very cool project. Here in the english community are very interessing coder.

Regards Blitzblaster (from the geman community) :-)

This adds two player restrictions on whether players can move further than the screen width and height.

This can be added in the loop just under the lines:
	move=False
	direct$=""
	mr=False
	ml=False
	mu=False
	md=False


	If pl=First player
		If KeyDown(205) And pl\x<7552 Then mr=True
		If KeyDown(203) And pl\x>0 Then ml=True
		If KeyDown(200) And pl\y>0 Then mu=True
		If KeyDown(208) And pl\y<7552 Then md=True
	Else
		If KeyDown(32) And pl\x<7552 Then mr=True
		If KeyDown(30) And pl\x>0 Then ml=True
		If KeyDown(17) And pl\y>0 Then mu=True
		If KeyDown(31) And pl\y<7552 Then md=True		
	EndIf
	

	If pl=First player ; player one
		p2.player=Last player
		If Abs(pl\y-p2\y) > (GraphicsHeight()-50)
			If pl\y < GraphicsHeight()/2
				mu=False
			Else
				md=False
			EndIf
		ElseIf Abs(pl\x-p2\x) > (GraphicsWidth()-50)
			If pl\x < GraphicsWidth()/2
				ml=False
			Else
				mr=False
			EndIf			
		EndIf
	ElseIf pl=Last player ; player two
		p2.player=First player
		If Abs(pl\y-p2\y) > (GraphicsHeight()-50)
			If pl\y < GraphicsHeight()/2
				mu=False
			Else
				md=False
			EndIf
		ElseIf Abs(pl\x-p2\x) > (GraphicsWidth()-50)
			If pl\x < GraphicsWidth()/2
				ml=False
			Else
				mr=False
			EndIf	
		EndIf	
	EndIf


Rob, can you give me a headsup on how I can start with bullets. What I want to know is: At what coords to create them and how to move them relative to movement. I'm confused!

Alien Breed had 2 types of gun...

Type 1 machine gun
Type 2 all other guns

The machine gun didn't actually have a bullet as such, it was a instant check down the path to see if it hits anything therefore no graphic was created apart from the gun flare.

The x,y of the player is the location it is on the map (in pixels), so relative co-ords are not necessary as the map/screen positions itself relative to the player co-ords.

The players can roam from 0,0 to 7552,7552.

So creation of the buttet will be at pl\x pl\y although you'll probably want to offset it a little so it doesn't start in the middle of the player.

The offset would be done (off the top of my head) x + (sin(dir*45))*offset and y + (cos(dir*45))*offset. The y bit might be a minus (not sure right now).

I'll try and give you a better idea later, I'll add your code in an update the zip, but it's just gone midnight, I've been drinking, and I need to go to bed!

I want to add an additional data layer to the map too so you'll be able to state what security level a door is for example, Antony, I assume this is cool for your new map format?

Anyway, it's good to see people picking up on this!

Not done it yet, rob, so if you make a little list of the things you definitely need it to support to work with what you have now/planned, I'll keep it mind when I code the loader/saver.(In the morning, bit late at night for that kinda stuff)

What I had in Alphabreed was a materals layer... this layer would be used to control what footstep sound effect would be played, so metal sfx on a matal material etc.

You might wanna add that too.

Add retreat fire from AlienBreed 2, player could walk backwards (a little slow than forwards) and fire is gun.

Might wanna add that too.

I'd like to create a simple hud, how could I create a HUD that would be on the left hand side of the screen? (I'm kind of new to this so no harsh comments.)

Do I need a GUI, if so which one would you reccommend?

Do I just create the graphics and save them as BMP and put them in and manually code in the health and other parts that are needed?

How can I transition from 1 image (character standing still) to him with his left leg out (walking) by pressing the left arrow to simulate him walking?

Thanks a million,
Chad

Coffee, Yeah, retreat fire is important, I preferred the tower assult version where if you're holding down fire and start moving the other way you automatically go into retreat mode.

Chad, I don't think we're ready for a hud yet as we don't know what the game is going to consist of, we don't know if you're going to have an inventory where you use objects with other objects or anything yet so any work on a hud will more than likly be changed by the time we need one. Also it'll have to be designed around 1 player or 2 players I would guess it'll be only half the screen wide with player 2's hud stuff mirrored on the other side of the screen.

The HUD itself needs to be as small and minimalist as possible as you need as much screen as possible for the action.

Regarding GUIs avoid them like the plague for a game, they'll be a massive overhead for no real advantage.

Rims, added your code to the zip. Seperated the zip into media and code so we don't need to keep downloading the media each time. New link on picture at the top.

How about making so that when you start firing your direction is locked. Then you are free to sidestep and walk backwards whilst firing, or are the controls up to walk forward and not to walk up?

I like that idea, the controls are up go up, down go down etc.

Rob,

Updated the following code to limit the screen movement to the size of the map (as it currently stands without modifiying for a particular map size)

If pl=First player
	If KeyDown(205) And pl\x<8192 Then mr=True
	If KeyDown(203) And pl\x>0 Then ml=True
	If KeyDown(200) And pl\y>0 Then mu=True
	If KeyDown(208) And pl\y<8192 Then md=True
Else
	If KeyDown(32) And pl\x<8192 Then mr=True
	If KeyDown(30) And pl\x>0 Then ml=True
	If KeyDown(17) And pl\y>0 Then mu=True
	If KeyDown(31) And pl\y<8192 Then md=True	
EndIf


Put this code just before the render world
;Limit movement of screen to map
If X < 0 Then X = 0
If X > 8192 - GraphicsWidth() Then X = 8192 - GraphicsWidth()
If Y < 0 Then y = 0
If Y > 8192 - GraphicsHeight() Then Y = 8192 - GraphicsHeight()


Also in the drawmap function the following is shown in each of the 4 layers:

If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yofff<=255

I believe y+yofff should be y+yoff ?

Here's a blast animation control include file.
Use setupBlastImages() at the beginning then drawBlasts() and handleBlasts() in the loop. Try:
if mousehit(1) then blastHere(1,mousex(),mousey(),0.3)



; blast.bb

Global small_blast_image
Global large_blast_image

Type blast
	Field x,y
	Field speed#
	Field frame#,kind
End Type

; call this to create a blast animation at these coords
; using kind=1 will create a small burst
; using kind=2 will create a big explosion
; a speed of 0.3 is quite good.
Function blastHere(kind,x,y,speed#)
	b.blast=New blast
	b\x=x : b\y=y 
	b\kind=kind
	b\frame=0:b\speed=speed	
End Function

Function handleBlasts()
	For b.blast=Each blast
		Select b\kind
			Case 1: max_frame=9
			Case 2: max_frame=6
		End Select
		If Int(b\frame) >= max_frame
			Delete b
		Else
			b\frame=b\frame+b\speed
		EndIf
	Next
End Function

Function drawBlasts()
	; draw the blast animation at its current int(frame)
	For b.blast=Each blast
		Select b\kind
			Case 1:DrawImage small_blast_image,b\x,b\y,Int(b\frame)
			Case 2:DrawImage large_blast_image,b\x,b\y,Int(b\frame)
		End Select
	Next	
End Function

; call this once on setup
Function setupBlastImages()
	small_blast_image=LoadAnimImage("gfx\gunsplater.png",32,32,0,10)
	large_blast_image=LoadAnimImage("gfx\frag.png",32,32,0,7)
	
	MaskImage small_blast_image,255,0,255
	MaskImage large_blast_image,255,0,255
End Function



Ok, here's a sound lib:
I got the explosion sound to test with from here:
http://www.sosbbs.com/~rwbenjamin/waveS.htm
http://www.sosbbs.com/~rwbenjamin/explo2.wav (free use)

call handleSounds() in the loop somewhere.

Use the function: playASound(file$,dat$="") to play a sound. You can specify string parameters that effect the sound like this:
PlayASound("explosion.wav","volume=0.4")
play it at 0.4 of the normal volume
PlayASound("explosion.wav","times=5")
play it five times
PlayASound("explosion.wav","volume=0.4,time=2")

or
PlayASound("explosion.wav")
to play a sound with normal volume and pitch and only play it once.

; sound.bb

Type sound
	Field file$
	Field hand,channel,times
	Field dat$[3],state$
End Type

; playASound("saveme.wav","volume=1.0,pitch=44000,times=1")
Function playASound(file$,dat$="")
	p.sound=New sound
	p\file=file	
	For i=0 To 3
		p\dat[i]=parse(dat,",",i)
	Next	
	p\hand=LoadSound(file)
	p\channel=PlaySound(p\hand)
	p\times=1	
	For i=0 To 3
		a$=parse(p\dat[i],"=",0)
		b$=parse(p\dat[i],"=",1)		
		If a = "" Then Exit			
		a=Lower(a):b=Lower(b)		
		Select a
			Case "volume":ChannelVolume(p\channel,b)
			Case "pitch":ChannelPitch(p\channel,b)
			Case "times":p\times=b
		End Select
	Next		
	p\state="play"
End Function

Function handleSounds()
	For s.sound=Each sound
		Select s\state
			Case "play"
				If ChannelPlaying(s\channel)=0
					; it's stopped playing. Play it again
					If s\times<>-1
						s\times=s\times-1
					EndIf
					If s\times>0 Or s\times=-1
						s\channel=PlaySound(s\hand)
					Else
						s\state="die"	
					EndIf
				EndIf
			Case "die"
				StopChannel(s\channel)
				FreeSound s\hand		
				Delete s						
		End Select
	Next
End Function

Function parse$(in$,de$,se)
    For x=1 To Len(in)
        v$=Mid(in,x,1)
        If v=de i=i+1
        If se=i And v<>de m$=m+v
    Next
    Return m
End Function


Here's a new version of the editor/map engine.
Added proper smooth scrolling.(Hold in rmb and drag mouse on map to scroll, even while editing)

Added line paste, this lets you drag a line(And scroll, it's not limited to the screen, it anchors to the tile under the mouse when you started)..it highlights what it'll draw, just drag and let go to paste.
Means you can now do most walls in two clicks, rather than manually doing each tile.

doing lightmapping part, now..here's where it gets intresting ;)
;For ;Top Down;
;
;
;Map and fx editor.
;
;Set up code by Rob Farley.
;
;Editor V2.0 Coded by Antony Wells.
;
;Open Source.

;-[setup by Rob farley.]
Include "M_Engine.bb"
Graphics 800,600,32,2
HidePointer
Global overBase.base,hitBase.base
Global tileW#=32,tileH#=32
Global maxtile = 190
Global tiles = LoadAnimImage("gfx/tiles.png",tileW,tileH,0,maxtile)
Global cursor = LoadImage("gfx/cursor.png")
MaskImage cursor,255,0,255
SetBuffer BackBuffer()
font = LoadFont("Arial.tff",15)
SetFont font
;-------------]
Global cTile.tile
genTiles()
Color 128,128,128
newButton( 10,540,60,20,"Load")
newButton( 80,540,60,20,"Save")
Color 255,0,0
newbutton( 150,540,60,20,"Clear")
;newButton( 220,540,60,20,"U
tileV.tile=First tile
viewY=300
ViewX=600
fromX=20
fromY=20
dragB.base=newButton(GraphicsWidth()/2-40,viewY-10,80,20,"Drag")
dragC.base=newButton(ViewX-20,viewY/2-20,40,40,"Pull")
dragA.base=newButton(20-10,20-10,20,10,"#")
dragD.base=newButton(fromX+viewX-10,fromY+viewY-10,20,20,"//")

Color 20,128,128
newText(GraphicsWidth()-100,5,"Edit Modes")
aMode.base=newText(GraphicsWidth()-150,40,"Mode:Paste")
pasteM.base=newButton(GraphicsWidth()-80,20,50,20,"Paste")
fillM.base=newButton(GraphicsWidth()-80,50,50,20,"Fill")
lineM.base=newButton(GraphicsWidth()-80,80,50,20,"Line")
lightM.base=newbutton(GraphicsWidth()-80,110,50,20,"Lights")
;lightM.base=newButton(GraphicsWidth()-80,130,50,20,"



Global overTile.tile
;---

;---[ Map Specific] 
	;set up default blank map
	initMap(555,555)
;-

Repeat
	Cls:uiCycle();
	mx#=MouseX()
	my#=MouseY()
	
	If MouseHit(1)
		Select state
			Case 0
				If overTile<>Null cTile=overTile
		End Select
	EndIf
	If MouseHit(2)
		Select state
			Case 0
				If overTile<>Null
					If ctile<>Null
						tnTile.tile=Before cTile
						Insert cTile Before overTile
						Insert overTile After tnTile
					EndIf
					
				EndIf
				
		End Select
	EndIf
	
	mxs=MouseXSpeed()
	mys=MouseYSpeed()
	FlushMouse
	Select uiHit()
		Case "Paste"
			cMode=1
			rename(amode,"Mode:Paste")
		Case "Fill"
			cMode=2
			rename(amode,"Mode:Fill")
		Case "Line"
			cMode=3
			rename(amode,"Mode:Line")
		Case "Lights"
			cMode=4
			rename(aMode,"Mode:Lights")
		Case "Drag"
		
			viewY=mY-fromY
		Case "Pull"
			viewX=mX-fromX
		Case "#"
			fromX=mx-viewX/2
			fromY=my
			dragA\x=mx+20
			dragA\y=my-10
		;	viewX=fromX
		Case "//"
			viewY=mY-fromY
			viewX=mX-fromX
		Default
			If MouseDown(3)
				If overTile<>Null
					If Not MouseDown(1)
						fromX=fromX+mxs
						fromY=fromY+mys
							dragA\Y=draga\y+mys
					Else
				
					viewX=viewX+mxs
					viewY=viewY+mys
					EndIf
				EndIf
				
			EndIf
			
	End Select
	FlushMouse 
	dragA\w=viewX
	draga\x=fromX
	dragD\x=viewX-10+fromX
	dragD\y=viewY-10+fromY
	dragB\y=viewY-10+fromY
	DragB\x=viewX/2-40+fromX
	dragC\x=viewX-20+fromX
	dragC\y=viewY/2-20+fromY
mz=MouseZSpeed()
If mz>0
	For mz=mz To 0 Step -1
	tileV=After tileV
	If tileV=Null tileV=First tile
	Next
Else If mz<0
	For mz=Abs(mz) To 0 Step -1
	tileV=Before tileV
	If tileV=Null tileV=Last tile
	Next
EndIf






	
	;-[ The following code contains the parts that actually edit the map)

	
	renderMap()
	dumpTiles(tileV,fromX,fromY,viewX,viewY)
	
	If cTile<>Null DrawImage cTile\id,MouseX(),MouseY()
	
	If Not ((mx>fromx And mx<(fromx+viewX) And my>fromY-10 And my<fromy+viewY) Or overBase<>Null Or hitBase<>Null)
		tileX=mapx+Int(mx+xoff)/Int(tileW)
		tileY=mapy+Int(my+yoff)/Int(tileH)
		Color 255,0,0
		Rect (tileX-mapX)*tileW-xoff,(tiley-mapY)*tileH-yoff,tileW,tileH,0
		If MouseDown(1)
			Select cMode
			Case 4
				If nullLights=False
				;	addLight()
					nullLights=True
				EndIf
			Case 2
				fillTile(cTile,tileX,tileY)
			Case 3
				If lineIn=False
					startX=mx
					startY=my
					tileSX=tileX
					tileSY=tileY
					lineIn=True
				Else
					tileEX=tileX
					tileEy=tileY
					endX=mx
					endY=my
					lineHighLight(tileSx,tileSy,tileEx,tileEy)
					
				EndIf
				
			Default 
				pasteTile(cTile,tileX,tileY)
			End Select
			
		Else
			If lineIn
				;Line startx,starty,endx,endy
				lineTile(ctile,tilesx,tilesy,tileex,tileey)
				lineIn=False
			EndIf
		EndIf
		If MouseDown(2)
			Select cMode
				Case 2,1,3,4
					scrollMap(-mxs*0.7,-mys*0.7)
		End Select
		EndIf
	EndIf
	
		Color 255,255,255
;	Rect fromX,fromY+viewY,ViewX,4
;	Rect fromX+viewX,fromY,4,viewY
	Rect fromX,fromY,viewX,viewY,0	

	
	
	renderGui()
	
	
	;This lets you shift the mouse cursor to the closet button
	;in the direction the mouse is moving when you press TAB
	;This speeds up editing a lot.
	If KeyDown(15)
		cx#=Float(MouseX())+Float(mxs)*6
		cy#=Float(MouseY())+Float(mys)*6
			xb=Sgn(mxs)
		yb=Sgn(mys)
		cbase.base=Null
		sd#=999999
		If MilliSecs()>ws+500
		For b.base =Each base
			If b\is=ui_button And b<>overBase
				ix#=b\x+b\w/2
				iy#=b\y+b\h/2
				xd#=ix-cx
				yd#=iy-cy
				bx=Sgn(xd)
				by=Sgn(yd)
				
				If bx=xb And by=yb
				td#=Sqr(xd*xd+yd*yd)
				If td<sd 
					cbase.base=b
					sd=td
					ws=MilliSecs()
				EndIf
				EndIf
			EndIf
		Next
		If cbase<>Null
	
			lockX=cbase\x+cbase\w/2
			lockY=cbase\y+cbase\h/2
			DrawImage cursor,lockx,lockY
			Flip
			Repeat
				
			Until KeyDown(15)=0
			MoveMouse lockX,lockY
			FlushMouse 	
		
		EndIf
		
		
		EndIf
	EndIf
	DrawImage cursor,MouseX(),MouseY()
	Color 255,0,0
		If lineIn
				Line (tilesx-mapx)*tileW+tileW/2-xoff,(tilesy-mapy)*tileh+tileH/2-yoff,endx,endy
				
				
			EndIf
	Color 255,255,255
	Text 1,1,mxs+" >"+mys
	;--
	Flip
Until KeyDown(1)

Function saveMap()
End Function

Function loadMap()

End Function



Function genTiles()	
	For j=0 To maxTile-1
		t.tile =New tile
		t\id=CreateImage(tileW,tileH)
		CopyRect 0,0,tileW,tileH,0,0,ImageBuffer(tiles,j),ImageBuffer(t\id)
		If imageEmpty(t\id)
			FreeImage t\id
			Delete t
		EndIf
		
	
	Next
End Function


Function dumpTiles(t.tile,x,y,maxWidth=250,maxHeight=250,smartDump=True,checkMouse=True)
	ox#=x
	oy#=y
	If t=Null t=First tile
	mx#=MouseX()
	my#=MouseY()
	Viewport x,y,maxWidth,maxHeight
	If checkMouse overTile=Null
	dispW=GraphicsWidth()
	dispH=GraphicsHeight()
	start.tile=t
	Repeat
		tc=tc+1
		DrawImage t\id,x,y
		If checkMouse
			If mx>x And mx<x+tileW
			If my>y And my<y+tileH
				overTile=t
			EndIf
			EndIf
		EndIf
		If t=cTile
			Color 255,255,255
			Rect x,y,tilew,tileh,0
		EndIf
		
		x=x+tileW
		If smartDump
			If x=>ox+maxWidth
				x=ox
				y=y+tileH
				If y=>oy+maxHeight-1 Exit ;y=0
			EndIf
		EndIf
		t=After t
		If t=Null t=First tile 
	Until t=start
	Viewport 0,0,GraphicsWidth(),GraphicsHeight()
	;DebugLog tc
End Function

Function uiCycle()
mx=MouseX()
my=MouseY()
Local but[3]
but[0]=MouseDown(1)
but[1]=MouseDown(2)
but[2]=MouseDown(3)

If but[0]=False hitBase=Null
overBase=Null
	For b.base=Each base
		If mx>b\x And mx<b\x+b\w
		If my>b\y And my<b\y+b\h
			overBase=b
			If but[0] 
				If hitbase=Null hitBase=overBase 
			EndIf
		EndIf
		EndIf
		
	Next	
	
End Function

Function uiHit$()
	If hitBase<>Null Return hitbase\id
End Function


Function uiOver$()
	If overBase<>Null Return overBase\id
End Function





;--- DO CUBIC LIGHTING FOR CRYO NEXT< YO
Function imageEmpty(image,imagePoint=5000,maskR=255,maskG=0,maskB=255,resetMask=True)

	SetBuffer ImageBuffer(image)
	LockBuffer
	iw=ImageWidth(tiles)
	ih=ImageHeight(tiles)
	For x=0 To ImageWidth(image)-1
	For y=0 To ImageHeight(image)-1
		rgb=ReadPixelFast(x,y)
		r#=(rgb Shr 16) And 255
		g#=(rgb Shr 8) And 255
		b#=(rgb And 255)
		If resetMask
			If r=maskR And b=maskB And g=MaskG
				WritePixelFast(x,y,0 Or (0 Shl 8) Or (0 Shl 16))
				r=0
				g=0
				b=0
			EndIf
		EndIf
		rd#=r-lr#
		gd#=g-lg#
		bd#=b-lb#
		shift#=shift+Sqr(rd*rd+gd*gd+bd*bd)
		lr#=r
		lg#=g
		lb#=b
	Next
	Next
	UnlockBuffer
	SetBuffer BackBuffer()
	If shift>imagePoint Return False
	Return True
End Function

;-SmallGUI ;just buttons for now, but will expand for the game it's self.

Type cache
	Field img
	Field x,y,width,height
End Type

Type base
	Field is
	Field x,y,w,h
	Field id$,r,g,b
End Type
Global doCache=0
Const ui_button=1,ui_text=2
Function newButton.base(x,y,w,h,title$)
	b.base= New base
	b\is=ui_button
	b\x=x
	b\y=y
	b\w=w
	b\h=h
	b\r=ColorRed()
	b\g=ColorGreen()
	b\b=ColorBlue()
	b\id=title
	doCache=True
	Return b
;	Return Handle(b)
End Function

Function newText.base(x,y,txt$)
	b.base=New base
	b\x=x
	b\y=y
	b\is=ui_text
	b\id=txt
	b\r=ColorRed()
	b\g=ColorGreen()
	b\b=ColorBlue()
	doCache=True
	Return b
End Function

Function rename(in.base,txt$)
	in\id=txt
End Function


Function renderGui()
	For b.base =Each base
		Select b\is
			Case ui_button
				
				Color 20,20,20
				Rect b\x+5,b\y+5,b\w,b\h,1
				
				If hitbase=b
					xm#=5
					ym#=5
				Else
					xm=0
					ym=0
				EndIf
				Color b\r,b\g,b\b
				Rect b\x+xm,b\y+ym,b\w,b\h
				Color 255,255,255
				Rect b\x+xm,b\y+ym,b\w-1,b\h-1,0
				Color 40,40,40
				Rect b\x+xm+1,b\y+ym+1,b\w-1,b\h-1,0
				Color 10,10,10
				Text b\x+xm+b\w/2,b\y+ym+b\h/2,b\id,True,True
				Color 255,255,255
				Text b\x+xm+b\w/2,b\y+ym+b\h/2-3,b\id,True,True
				
			Case ui_text
			
				Color 5,5,5
				Text b\x+4,b\y+4,b\id
				Color b\r,b\g,b\b
				Text b\x,b\y,b\id
				
		End Select
	Next
	
End Function

Function genCaches()
	sx#=9999
	sy#=9999
	bx#=-9999
	sy#=-9999
	For b.base =Each base
		x2#=b\x+b\w
		y2#=b\y+b\h
		If b\x<sx sx=b\x
		If b\y<sy sy =b\y
	Next
	
End Function


;Map Engine 2
;
;Original coded by Antony Wells

Type tile
	Field id
End Type

Dim map.tile(0,0,0)
Dim info#(0,0,0,15) ;just temp info for the map editor alone.
Global mapWidth,mapHeight,mapDepth
Global xoff#,yoff#,mapX#,mapY# ;mapx,y in tiles, xoff/yoff offset in pixels(Within range of 0 to tileWidth-1)
Global tileWidth,tileHeight



Function scrollMap(x#,y#) ;in pixels.
	xOff=xOff+x
	yOff=yOff+y
	
	If xOff<0 
		mapX=mapX-1
		xoff=tileWidth-Abs(xoff)
	Else If xOff>tileWidth
		mapX=mapX+1
		xoff=xoff-tileWidth
	EndIf
;	Return 
	
	
	If yOff<0
		mapy=mapY-1
		yoff=tileHeight-Abs(yoff)
	Else If yOff>tileHeight
		mapy=mapy+1
		yoff=yoff-tileHeight
		
	EndIf
;	xoff=Wrap(xoff,tileWidth)
;	ypff=Wrap(yoff,tileHeight)
End Function


;recursive wrap. 
Function Wrap#(val#,top#)
	If val<0 
		val=top-Abs(val)
	EndIf
	If val>top
		val=val-top
	EndIf
	Return val
End Function

Function initMap(width,height,tileW2=32,tileH2=32,depth=4)
	Dim map.tile(width,height,depth)
	Dim info(width,height,depth,15)
	mapWidth=width
	mapHeight=height
	tileWidth=tileW2
	tileHeight=tileH2
	mapDepth=depth
End Function

Function pasteTile(tile.tile,x,y,layer=1)
	If x<0 Or x>mapWidth Or y<0 Or y>mapheight Or layer<0 Or layer>mapDepth Return 
	map(x,y,layer)=tile
End Function

Function fillTile(tile.tile,x,y,layer=1,smartFill=False)
    If smartFill
    Else
		For mx=0 To mapWidth-1
		For my=0 To mapHeight-1
			map(mx,my,layer)=tile
		Next
		Next
	EndIf
End Function

Function highLight(sx,sy,layer=1)
	info(sx,sy,layer,1)=True
End Function

Function lineHighlight(sx#,sy#,ex#,ey#,layer=1)
	xd#=ex-sx
	yd#=ey-sy
	If Abs(xd)>Abs(yd) steps=Abs(xd) Else steps=Abs(yd)
	xi#=xd/Float(steps)
	yi#=yd/Float(steps)
	For steps=steps To 0 Step -1
		highlight(sx,sy,layer)
		sx=sx+xi
		sy=sy+yi
	Next
	

End Function


Function lineTile(tile.tile,sx#,sy#,ex#,ey#,layer=1)
	xd#=ex-sx
	yd#=ey-sy
	If Abs(xd)>Abs(yd) steps=Abs(xd) Else steps=Abs(yd)
	xi#=xd/Float(steps)
	yi#=yd/Float(steps)
	For steps=steps To 0 Step -1
		pasteTile(tile,sx,sy,layer)
		sx=sx+xi
		sy=sy+yi
	Next
	
End Function


Function clearMap()
	Dim map.tile(mapWidth,mapHeight,mapDepth)
End Function

Function renderMap()

	tileHorz=GraphicsWidth()/tileWidth ;how many tiles we can see horizontally.
	tileVert=GraphicsHeight()/tileHeight ;vertically speaking, this is the same.
	For td=1 To mapDepth
	For tx=mapX To mapX+TileHorz
		If tx>-1 And tx<mapWidth
			For ty=mapY To mapY+tileVert
				If ty>-1 And ty<mapheight 
					tile.tile=map(tx,ty,td)
					
					If tile<>Null
						ax=rx*tileWidth-xoff
						ay=ry*tileHeight-yoff
						DrawImage tile\id,ax,ay
						If info(tx,ty,td,1)
							info(tx,ty,td,1)=False
							Color 255,255,255
							Rect ax,ay,tileW,tileH,0
						EndIf
					EndIf
					
				EndIf
				ry=ry+1
			Next
			ry=0
		EndIf
	rx=rx+1
	Next
	
	Next
	
	
End Function



Thanks for your reply. I guess I'll follow along with these updates and learn as I go.

Cool project...
Not much time for my input, busy doing other projects. Would love to help though.

There should be another map level, for slopes and sticky/death areas that player falls, gets stuck in etc.
I belive the original AB had these to add to the 3D effect.

It was def used on the last level, with the alien-esque nest.

I would like to help, but I don't have the skills.

Your guys should make it multiplayer with atleast possibility for 8 people to play in the same game :) some coop and massive ammounts of enemies comming at you :)

always thought multiple player (2+) would be good fun

The engine is suitable for any amount of players, players are just stored in a type, it's just down to lack of network code that is the restriction.

Peronally though I think for simplisity we should stick to 2 or at least make it so it's a cram round the keyboard job of up to any amount of players. This of course causes the keyboard lock up problems (only 4 keys at a time) however, you can plug as many USB keyboards into a computer at one time to solve this problem (if you want to!)

Ok, I've added a set of global vars to offset all drawing in other parts of the program. Add
Global GOffsetX,GOffsetY
to the main program.
And:
 	GOffsetX=x
	GOffsetY=y

after
; put screen in average player position
x=x/count
y=y/count

x=x-320
y=y-240

these lines in the loop.


Here's a basic working shooting include:
; weapons.bb

Type bullet
	Field x#,y#
	Field vx#,vy#
	Field owner.player
	Field life
End Type

Function shoot(p.player,angle,speed#)
	Local offset#=32.0

	b.bullet=New bullet
	b\owner=p
	; add offset an position
	b\x=(p\x-GOffsetX)+Sin(angle)*offset
	b\y=(p\y-GOffsetY)+-Cos(angle)*offset		
	
	b\vx=Sin(angle)*speed
	b\vy=-Cos(angle)*speed	
	; create muzzle flash	
End Function

Function handleBullets()
	For b.bullet=Each bullet
		ok=True		
		
		bx=b\x-GOffsetX
		by=b\y-GOffsetY
		
		If bx < 32 Then ok=False
		If by < 32 Then ok=False
		If bx > 7552 Then ok=False
		If by > 7552 Then ok=False
		
		If ok=True			
			result=gettile(b\x+GOffsetX,b\y+GOffsetY,0)
			If result
				; hit a wall. create a blast
	             blastHere(Rand(1,2),b\x-16,b\y-16,0.3)
				ok=False
			EndIf
		EndIf
		
		b\x=(b\x+b\vx)
		b\y=(b\y+b\vy)		

		If ok=False Then Delete b
	Next	
End Function

Function drawBullets()
	Color 255,255,255
	For b.bullet=Each bullet
		bx=b\x-GOffsetX
		by=b\y-GOffsetY	
		Rect b\x,b\y,2,2
	Next	
End Function	


Put drawBullets() and handleBullets() in the loop somewhere. To use the shooting, use:
	If pl=First player
		If KeyHit(57) ; Space
			shoot(pl,pl\dir*45,8)
		EndIf
	Else
		If KeyHit(29) ; Left Ctrl
			shoot(pl,pl\dir*45,8)
		EndIf
	EndIf

in the player for..next loop.

Also, here's an updated blast.bb file to accomodate the GOffsetX and GOffsetY.
; blast

Global small_blast_image
Global large_blast_image

Type blast
	Field x,y,sx,sy
	Field speed#
	Field frame#,kind
End Type

; call this to create a blast animation at these coords
; using kind=1 will create a small burst
; using kind=2 will create a big explosion
; a speed of 0.3 is quite good.
Function blastHere(kind,x,y,speed#)
	b.blast=New blast
	b\x=x : b\y=y 
	b\sx=b\x+GOffsetX : b\sy=b\y+GOffsetY
	b\kind=kind
	b\frame=0:b\speed=speed	
End Function

Function handleBlasts()
	For b.blast=Each blast
		p.player=First player

		b\x=b\sx-GOffsetX
		b\y=b\sy-GOffsetY
	
		Select b\kind
			Case 1: max_frame=9
			Case 2: max_frame=6
		End Select
		If Int(b\frame) >= max_frame
			Delete b
		Else
			b\frame=b\frame+b\speed
		EndIf
	Next
End Function

Function drawBlasts()
	; draw the blast animation at its current int(frame)
	For b.blast=Each blast
		Select b\kind
			Case 1:DrawImage small_blast_image,b\x,b\y,Int(b\frame)
			Case 2:DrawImage large_blast_image,b\x,b\y,Int(b\frame)
		End Select
	Next	
End Function

; call this once on setup
Function setupBlastImages()
	small_blast_image=LoadAnimImage("gfx\gunsplater.png",32,32,0,10)
	large_blast_image=LoadAnimImage("gfx\frag.png",32,32,0,7)
	
	MaskImage small_blast_image,255,0,255
	MaskImage large_blast_image,255,0,255
End Function


Looking great. Always wondered what happend to "alpha breed". I have one problem, is there someone who is centralizing the latest version of this project? If I go on vacation for a month and I come back I think I can't figure out anymore what is what part and make a complete game of it...

I'm doing it (seeing as I'm hosting it), but I can't do it every minute of the day so I do it once in the evening.

I make sure everything works before I upload and add a couple of bits here and there to smooth out the cracks. This takes a bit of time, hence the once a day thing.

Every time I update the zip I put a post on this thread saying the zip is updated and what updates have been made. I'm also updating the history file in zips and the general documentation (of which there is bugger all!).

I've not added Antony's Mapper yet as I've no idea how it'll be implemented in the game, I'll have to take a closer look at the at some point soon.

yeah don't worry about that, I'll integrate the editor myself when the time comes.

Code zip updated. Added blast and weapons includes from Rims.

Shooting appears to be a little buggy as sometimes the shots don't seem to go the distance... I'll see if I can look into getting that sorted.

We're moving frightenly close to needing an alien bad guy, I'll see if I can come up with a place holder until someone who can draw comes up with something better!

I was wondering if the game could be coded so the graphics engine is completely separate from the game engine.

If the game source included the graphics engine you could swap between a medialess wireframe version, a 2D megapixel display engine and a full on 3D version.

I would be interested in coding some procedural routines for the medialess engine based on a simple vector engine type design.

In regards to character animation for the 2D version maybe we can start with some stock b3d models and render the frames from Blitz3D?

How are we supposed to keep adding updates and what not? Just keep posting thru these forums?

I took a look at whats been done thus far...I haven't added much in terms of functionality but I did move and revise some of the player code into its own include. The 'engine.bb' file is looking a bit messy.

Also, hows all this going to be glued together? I see problems down the road if theres no standard for contributers on how to write, modify and interface code.

Rob,

Noticed that you cannot change direction (either side of current) if up against a wall. Change the code to allow the player to move/slide along the wall.

If mr Then
	If gettile(pl\x+playerradius,pl\y,0)=0 Then 
		pl\x=pl\x+1:move=True
	End If	
	direct=direct+"R"
End If
If ml Then 
	If gettile(pl\x-playerradius,pl\y,0)=0 Then 
		pl\x=pl\x-1:move=True
	End If
	direct=direct+"L"
End If
If mu Then
	If gettile(pl\x,pl\y-playerradius,0)=0 Then 
		pl\y=pl\y-1:move=True
	End If
	direct=direct+"U"
End If
If md Then 
	If gettile(pl\x,pl\y+playerradius,0)=0 Then 
		pl\y=pl\y+1:move=True
	End If	
	direct=direct+"D"
End If



> I was wondering if the game could be
> coded so the graphics engine is completely
> separate from the game engine.

So it can be delta timed?

I was wondering if the game could be coded so the graphics engine is completely separate from the game engine.
It kind of is already if we continue with detecting collision through maths rather than through images collide etc then there's no reason why a 3D map couldn't be used instead as the rendering of the map is just set the XY co-ord and it draws it there.

Also, hows all this going to be glued together? I see problems down the road if theres no standard for contributers on how to write, modify and interface code.
That's what I'm doing, I'm reviewing all (ahem) code before it goes in and trying to keep it to one standard(ish). This is why (as I stated earlier) I'm only doing one upload a day, this way there's some control over the versioning, and I'm updating the supporting files to keep everyone who contributed creditted. Po-ed, add any code you've done to the forums letting me know where it goes and what it does.

Matt, I noticed that too after adding the blast and weapon includes, I'll add your code tonight.

You should use some kind of input binding code for the controls.
So for example you can assing the joypad buttons and the keyboard for the same player and still just use one command to get if the player is walking up or shooting.

I wrote a usefull system like this some weeks ago if your interested. Its quite easy to use and implement
just replace "if keydown(200)" with "if walkup\down>0" and at the start u attach the keys,mousebuttons,joypad to each player button.

If any interest ill share my code

Space, that's exactly what will be happening, your code would be great so we don't have to re-invent the wheel. The current state of it is just for simplicity and getting the basic engine up and running.

Rob,

Checked the firing code Rims wrote and have fixed the issue where the bullets didn't move correctly:

Function handleBullets()
	For b.bullet=Each bullet
		ok=True		
		
		bx=b\x	;-GOffsetX
		by=b\y	;-GOffsetY


Don't know if anyone else has noticed (may be my keyboard), but I cannot fire when pointing Up/Left and pressing the space bar. Works fine if I use another key such as Left/Right Ctrl.

Matt, that's a keyboard thing, if ctrl was used instead of space it'll probably work. PC keyboards aren't designed for games and therefore have big problems with lots of keys being hit at the same time.

Anyway as Space said, once there's a control binder in there it'll be up to the user what keys/joystick/pad they use. It's really not worth worrying about at this stage.

Guys,

Heres the new "players.bb" and "engine.bb" include(called "engine_cleanup1.bb"). "players.bb" should go in the inc\ folder.

I've added nothing in terms of features, but I think this is a welcome cleanup :)

"players.bb"

new functions:

Player_Create.player(Name$,X%,Y%,id%) - Constructor
Player_Free() - Destructor
Player_UpdateAll() - Iterates thru each player

see the include for more notes.
;==========================================================================================
;"players.bb"
;==========================================================================================
;Author: RobFarley?? Rims??
;Purpose: Create, Manipulate, and Free Players.
;
;To do's: Break up player input with "event layer" (for key remapping/ networking/etc)
;
;History:
;	- 8/31/2004 POedBoy
;		
;		This module was created as a Tidy up/Maintenance move. Player specific code
;		should now be centralized within this include. Player.player() array added allows
;		direct indexing to a player(if used). Blackbox functions for Create/Destroy. Not too sure as
;		what the accepted naming schemes are at this point soo please bear with. 


;==========================================================================================
;TYPES
;==========================================================================================
Type player
	Field name$
	Field x
	Field y
	Field frame
	Field ammo
	Field health
	Field fpause
	Field dir
	Field id
End Type

;==========================================================================================
;GLOBALS AND ARRAYS
;==========================================================================================
Dim Player.player(2);Array of types for direct indexing to all players
					;not currently used -- needs the big group "okay"

Global Player_Count = 0 ;used by screen centering code? 
Global playerradius = 20; too lazy to see what this does :) (was floating around in main include)
Global playergfx = LoadAnimImage("gfx/player.png",64,64,0,240) : MaskImage playergfx,255,0,255



 
;==========================================================================================
;FUNCTIONS
;==========================================================================================	
Function Player_Create.player(Name$,X%,Y%,id%)
	Local pl.player = New player
	
	pl\name = Name$
	pl\x = X
	pl\y = Y
	pl\frame = 0
	pl\ammo = 0
	pl\health = 100
	pl\fpause = 0
	pl\dir = 0
	pl\id = id ; think this field could be made redundant-- but its there soo..
	
	Return pl
End Function

Function Player_Free(pl.player)
	;in the future -- if any resources/objects are linked to this player,
	;they can be freed here--
	;...
	;...
	;for now-- just 'deletes' the player obj
	Delete pl.player
		
End Function

Function Player_UpdateAll()
	
	ScreenX=0
	ScreenY=0
	Player_Count=0 
	
	For pl.player = Each player

	move=False
	direct$=""
	mr=False
	ml=False
	mu=False
	md=False
	
	If pl=First player
		If KeyDown(205) And pl\x<7552 Then mr=True
		If KeyDown(203) And pl\x>0 Then ml=True
		If KeyDown(200) And pl\y>0 Then mu=True
		If KeyDown(208) And pl\y<7552 Then md=True
		If KeyHit(57) ; Space
			shoot(pl,pl\dir*45,8)
		EndIf
	Else
		If KeyDown(32) And pl\x<7552 Then mr=True
		If KeyDown(30) And pl\x>0 Then ml=True
		If KeyDown(17) And pl\y>0 Then mu=True
		If KeyDown(31) And pl\y<7552 Then md=True
		If KeyHit(29) ; Left Ctrl
			shoot(pl,pl\dir*45,8)
		EndIf		
	EndIf
	

	If pl=First player ; player one
		p2.player=Last player
		If Abs(pl\y-p2\y) > (GraphicsHeight()-50)
			If pl\y < GraphicsHeight()/2
				mu=False
			Else
				md=False
			EndIf
		ElseIf Abs(pl\x-p2\x) > (GraphicsWidth()-50)
			If pl\x < GraphicsWidth()/2
				ml=False
			Else
				mr=False
			EndIf			
		EndIf
	ElseIf pl=Last player ; player two
		p2.player=First player
		If Abs(pl\y-p2\y) > (GraphicsHeight()-50)
			If pl\y < GraphicsHeight()/2
				mu=False
			Else
				md=False
			EndIf
		ElseIf Abs(pl\x-p2\x) > (GraphicsWidth()-50)
			If pl\x < GraphicsWidth()/2
				ml=False
			Else
				mr=False
			EndIf	
		EndIf	
	EndIf
	
	; door objects 7 and 8, opendoor function needs to be replaced with animation stuff
	If mr And gettile(pl\x+playerradius,pl\y,2)=7 Then If keycheck(pl\id) Then opendoor((pl\x+playerradius)/32,pl\y/32)
	If ml And gettile(pl\x-playerradius,pl\y,2)=7 Then If keycheck(pl\id) Then opendoor((pl\x-playerradius)/32,pl\y/32)
	If mu And gettile(pl\x,pl\y-playerradius,2)=8 Then If keycheck(pl\id) Then opendoor(pl\x/32,(pl\y-playerradius)/32)
	If md And gettile(pl\x,pl\y+playerradius,2)=8 Then If keycheck(pl\id) Then opendoor(pl\x/32,(pl\y+playerradius)/32)
	
	
	If mr And gettile(pl\x+playerradius,pl\y,0)=0 Then pl\x=pl\x+1:move=True:direct=direct+"R"
	If ml And gettile(pl\x-playerradius,pl\y,0)=0 Then pl\x=pl\x-1:move=True:direct=direct+"L"
	If mu And gettile(pl\x,pl\y-playerradius,0)=0 Then pl\y=pl\y-1:move=True:direct=direct+"U"
	If md And gettile(pl\x,pl\y+playerradius,0)=0 Then pl\y=pl\y+1:move=True:direct=direct+"D"
	
	
	
	If move
		pl\fpause = (pl\fpause+1) Mod 5
		If pl\fpause = 0 Then pl\frame = (pl\frame+1) Mod 15
	EndIf

	If direct = "U" Then pl\dir=0
	If direct = "RU" Then pl\dir =1
	If direct = "R" Then pl\dir =2 
	If direct = "RD" Then pl\dir = 3
	If direct = "D" Then pl\dir = 4
	If direct = "LD" Then pl\dir = 5
	If direct = "L" Then pl\dir = 6
	If direct = "LU" Then pl\dir = 7
	
	
	ScreenX = ScreenX + pl\x
	ScreenY = ScreenY + pl\y
	Player_Count = Player_Count+1
	
	
	; collect objects
	If gettile(pl\x,pl\y,2)>0
		p.pickedup = New pickedup
		p\player = pl\id ; allowing for multiple players
		p\obj = gettile(pl\x,pl\y,2)
		puttile(pl\x,pl\y,2,0)
	EndIf
	
Next
End Function

;additional player specific functions can be added here later as needed..

theres probably still some player stuff in the main engine include(I know the player drawing is), but we'll get this sorted out as time goes on.


"engine_cleanup1.bb"

changes:

-the player initialization and player updating routines have been moved to "players.bb" as functions, and are called from this include.

-I don't want to break anyones code but there were the odd locals floating around that seem to be only used by the player or screen code. I've changed the locals "x,y" to globals "ScreenX,ScreenY". Local "count" has been moved to "Players.bb" as global "Player_Count".

; tiles
Graphics 640,480,32,2
SetBuffer BackBuffer()

Global ScreenX,ScreenY ; replaces locals "x,y"

Global GOffsetX,GOffsetY

Include "inc\players.bb"
Include "inc\weapons.bb"
Include "inc\blast.bb"

setupBlastImages()


maxtile = 435
maxobject = 15
Global tiles = LoadAnimImage("gfx/tiles.png",32,32,0,maxtile)
Global objects = LoadAnimImage("gfx/objects.png",32,32,0,maxobject)
MaskImage tiles,255,0,255
MaskImage objects,255,0,255




Dim map(255,255,4)
; CollsionLayer = 0
; baselayer = 1
; ObjectLayer = 2
; TopLayer = 3
; Blocktoplayer = 4

; load map
load("test")

; object names
Data "Ammo","Health","Generic Key","Red Key","Green Key","Blue Key","V Door","H Door"
Dim objectname$(8)
For n=1 To 8
	Read objectname(n)
Next


;Player Initialization - name, x, y, id
Player_Create.player("Player #1",320,240,1)
Player_Create.player("Player #2",320,300,2)

Type pickedup
	Field player
	Field obj
End Type


ups=120
period=1000/ups
time=MilliSecs()-period

Repeat

; timing code
Repeat
elapsed=MilliSecs()-time
Until elapsed
tic=elapsed/period
For k=1 To tic
	time=time+period
	ticks=ticks+1
	
	; the gettile checks the collision layer (0) in the direction that you're trying to move
	; if there's a collsion block there it won't let you.
	; this needs extending a little as you can get half way into a block if you try hard enough!
	

Player_UpdateAll()

; put screen in average player position
ScreenX = ScreenX/Player_Count
ScreenY = ScreenY/Player_Count

ScreenX = ScreenX-320
ScreenY = ScreenY-240

;Limit movement of screen To map
If ScreenX < 0 Then ScreenX = 0
If ScreenX > 8192 - GraphicsWidth() Then ScreenX = 8192 - GraphicsWidth()
If ScreenY < 0 Then ScreenY = 0
If ScreenY > 8192 - GraphicsHeight() Then ScreenY = 8192 - GraphicsHeight()

GOffsetX=ScreenX
GOffsetY=ScreenY


Next
; end of timing code

; render world
		
drawmap(ScreenX,ScreenY,1)
drawmap(ScreenX,ScreenY,2)

drawbullets()



For pl.player = Each player

	DrawImage playergfx,pl\x-32-ScreenX,pl\y-32-ScreenY,pl\frame+(pl\dir*15)
	
Next

drawblasts()
handleblasts()
handlebullets()

drawmap(ScreenX,ScreenY,3)
drawmap(ScreenX,ScreenY,4)
; end of render



; temp hud to display objects collected
py1=15:py2=15
Color 255,255,255
Text 0,0,"Player 1 Items"
rText 640,0,"Player 2 Items"

Color 190,190,190
For p.pickedup = Each pickedup
	If p\player=1 Then Text 0,py1,objectname(p\obj):py1=py1+15
	If p\player=2 Then rText 640,py2,objectname(p\obj):py2=py2+15
Next


Flip
Until KeyHit(1)

Function rtext(x,y,words$)
x=x-StringWidth(words)
Text x,y,words
End Function

Function drawmap(xpos,ypos,layer)

; sort out the block location based on pixel co-ord
xoff = Floor(xpos/32)
yoff = Floor(ypos/32)

; find the pixel offset
xpxoff = (xoff * 32) - xpos
ypxoff = (yoff * 32) - ypos


; draw base layer
; uses draw block so you don't need a cls and is quicker.
If layer = 1
	For x = -1 To 20
		For y = -1 To 15
			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
			If map(x+xoff,y+yoff,layer)>0 Then DrawBlock tiles,(x*32)+xpxoff,(y*32)+ypxoff,map(x+xoff,y+yoff,layer)-1
			EndIf
		Next
	Next
EndIf

If layer = 2
	For x = -1 To 20
		For y = -1 To 15
			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
			If map(x+xoff,y+yoff,layer)>0 Then DrawImage objects,(x*32)+xpxoff,(y*32)+ypxoff,map(x+xoff,y+yoff,layer)-1
			EndIf
		Next
	Next
EndIf

; draw other layers
If layer = 3
	For x = -1 To 20
		For y = -1 To 15
			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
			If map(x+xoff,y+yoff,layer)>0 Then DrawImage tiles,(x*32)+xpxoff,(y*32)+ypxoff,map(x+xoff,y+yoff,layer)-1
			EndIf
		Next
	Next
EndIf

; layer 4, block overlay no transparancy
If layer = 4
	For x = -1 To 20
		For y = -1 To 15
			If x+xoff>=0 And y+yoff>=0 And x+xoff<=255 And y+yoff<=255
			If map(x+xoff,y+yoff,layer)>0 Then DrawBlock tiles,(x*32)+xpxoff,(y*32)+ypxoff,map(x+xoff,y+yoff,layer)-1
			EndIf
		Next
	Next
EndIf

End Function


; load the map in
Function load(filename$)
filein = ReadFile(filename+".map")
For layer = 0 To 4
	For x=0 To 255
		For y=0 To 255
			map(x,y,layer)= ReadInt(filein)
		Next
	Next
Next
CloseFile filein
End Function

; Get tile gets the tile under x,y (pixels) world co-ordinates
Function gettile(x,y,layer)
	; sort out the block location based on pixel co-ord
	x = Floor(x/32)
	y = Floor(y/32)
	Return map(x,y,layer)
End Function

Function puttile(x,y,layer,newtile)
	; sort out the block location based on pixel co-ord
	x = Floor(x/32)
	y = Floor(y/32)
	map(x,y,layer)=newtile
End Function

Function opendoor(x,y)
	map(x,y,2)=0
	map(x,y,0)=0
	
	If map(x,y-1,2)=7 Then opendoor(x,y-1)
	If map(x,y+1,2)=7 Then opendoor(x,y+1)
	If map(x+1,y,2)=8 Then opendoor(x+1,y)
	If map(x-1,y,2)=8 Then opendoor(x-1,y)
	
	
End Function

Function keycheck(player)

For p.pickedup = Each pickedup
If p\player = player And p\obj > 2 And p\obj < 7 Then Delete p:Return True
Next

Return False

End Function


Nice one Poed, I'll add that lot in this evening.

The ID isn't redundant as it gets passed when a player picks up an item and adds it to that id on the item list.

No worries about the keys - just thought I would point it out.

Zips Updated, you need to redownload code and media.

01-09-2004 :	Matt - Fixed the shooting bug
		Poed Boy - Seperated out the player code into functions and tidied up the main loop
		Rob Farley - Refixed the players getting stuck at edges bug!
		Rob Farley - Added alien gfx and basic alien handling code
31-08-2004 :	Rims - Blast and shooting includes (athough shooting appears to be a little buggy)
		Matt - Fixed players getting stuck at edges bug
29-08-2004 :	Rims - 2 Player code
		Rob Farley - Updated temp hud
		Rob Farley - Media, added block overlay on map, added object tiles.
		Rob Falrey - More Media, doors and keys now work. Door opening needs animation though
		Coffeedotbean kindly donated the media from his Alpha Breed project.
25-08-2004 :	Rob Farley - First release, basic map editor, game engine and tileset.


Also I mentioned it before but no-one commented:

Instead of one key = one door, how about security passes that let you obtain security access rights. Ie you start off with just basic access then as you venture deeper in you find higher security passes that allow you into rooms you couldn't get into before, eg, you find a Security Guards pass that allows you into an armoury for example, or an Techy pass that lets you into the computer rooms etc etc.

Discuss...

There's a pattern emerging... I add something and matt fixes it. lol! I think the latest media.zip is missing the alien gfx. or it might just be me!

I prefer the later key method rob. Specific keys for specific things.

nice one, guys, we're getting there.

I think there should still be specific keys for specific things, I just think if you had security levels too, I think it would be more realistic.

I was looking around the internet for some AB info and came across the original version on the PC which includes some of the sound effects.

Also Back to the Roots Amiga website (www.back2roots.org) has some of the intro music.

missing alien.png

modified editor.bb:

added:
scrollwheel now scrolls up and down tileset
created two variables: MouseOverTileset and MouseOverMap (guess what they do)
modified:
Changed the button function to accept an optional parameter (Symbol) which tells the function to use symbol.ttf as the font.
Changed the scroll tileset buttons to up and down arrows using the symbol font
Corrected spelling of Arial.ttf (was Arial.tff)
Corrected spelling of TileOffset variable in line:
If KeyDown(201) And tileoffset>0 And scrolldelay<0 Then tup=-1
so that PageUp works
; keys

; arrow keys move around map
; pgup/pgdown scroll through tiles
; return - pick up tile
; numpad4 - place a ground of 4 squares starting with the selected tile ie 12
;                                                                          34
; Space - Promote background tile to a over block tile



Graphics 800,600,32,0

maxtile = 410 ;set this to the number of tiles in the tileset
maxobject = 15
Global tiles = LoadAnimImage("gfx/tiles.png",32,32,0,maxtile)
Global objects = LoadAnimImage("gfx/objects.png",32,32,0,maxobject)
MaskImage tiles,255,0,255
MaskImage objects,255,0,255

Global cursor = LoadImage("gfx/cursor.png")
MaskImage cursor,255,0,255

SetBuffer BackBuffer()

Global font = LoadFont("Arial.ttf",15)
Global symbFont = LoadFont("Symbol.ttf",15)

SetFont font


; CollsionLayer = 0
; baselayer = 1
; ObjectLayer = 2
; TopLayer = 3
; Block top layer  = 4

Dim map(255,255,4)

SeedRnd MilliSecs()

For x=0 To 255
For y=0 To 255
t=Rand(-1,2)
If t=-1 Then t=15 Else t=t+31
map(x,y,1)=t
Next
Next

For n=1 To 2000
map(Rand(0,255),Rand(0,255),1)=Rand(16,35)
Next


x=0
y=0

scrolldelay = 0
setscrolldelay = 2

; layer visiblilty
Dim visible(4)
For n=0 To 4
	visible(n)=1
Next
Dim layername$(4)
layername(0)="Collision"
layername(1)="Base Layer"
layername(2)="Object Layer"
layername(3)="Top Layer"
layername(4)="Block overlay"


activelayer = 1

activetile = 0
tileoffset = 0

;BEGIN MAIN LOOP
Repeat
	Cls
	
	
	
	; draw layers
	For n=1 To 4
		If visible(n)=1 Then drawmap(x,y,n)
	Next
	If visible(0)=1 Then drawcollision(x,y)
	
	
	
	;gui

	mz = MouseZSpeed()
	
	If (MouseY()>490 And MouseY()<586) Then 
		If (MouseX()>32 And MouseX()<768) Then
			MouseOverTileset = True 
		EndIf
	Else
		MouseOverTileset = False
	EndIf
	
	If (MouseX()<640 And MouseY()<480) Then MouseOverMap = True Else MouseOverMap = False

	
	; slow down the scrolling a bit
	If scrolldelay < 0
		If KeyDown(205) And x<7552 Then x=x+32 : scrolldelay = setscrolldelay
		If KeyDown(203) And x>0 Then x=x-32 : scrolldelay = setscrolldelay
		If KeyDown(200) And y>0 Then y=y-32 : scrolldelay = setscrolldelay
		If KeyDown(208) And y<7552 Then y=y+32 : scrolldelay = setscrolldelay
	Else
		scrolldelay = scrolldelay - 1
	EndIf
	
	; find location
	If MouseOverMap Then
		xpos = Floor(MouseX()/32)+Floor(x/32)
		ypos = Floor(MouseY()/32)+Floor(y/32)
		Else
		xpos = -1
		ypos = -1
	EndIf
	
	If xpos>-1
		If MouseDown(1) And activelayer>0 Then map(xpos,ypos,activelayer)=activetile+1
		If MouseDown(1) And activelayer=0 Then map(xpos,ypos,activelayer)=1
		If MouseDown(2) And activelayer<>1 Then map(xpos,ypos,activelayer)=0
		If MouseDown(2) And activelayer=1 Then map(xpos,ypos,activelayer)=1
		
		If KeyDown(28) Then activetile = map(xpos,ypos,activelayer)-1
		
		If KeyDown(57) And map(xpos,ypos,1)>0 Then map(xpos,ypos,4) = map(xpos,ypos,1):map(xpos,ypos,1)=0
		If KeyDown(75)
			map(xpos,ypos,activelayer)=activetile+1
			map(xpos+1,ypos,activelayer)=activetile+2
			map(xpos,ypos+1,activelayer)=activetile+3
			map(xpos+1,ypos+1,activelayer)=activetile+4
		EndIf
	EndIf


	
	
	For n=0 To 4
		If activelayer=n Then act=True Else act=False
		If Button(650,n*20,100,layername(n),act) Then activelayer=n
		
		If Button(760,n*20,30,"Vis",visible(n))
			visible(n)=(visible(n)+1) Mod 2
			Repeat:Until MouseDown(1)=False
		EndIf
	Next
	
	
	Button(650,130,50,xpos)
	Button(710,130,50,ypos)
	
	;cursor
	If xpos>-1
		Color 0,255,0
		Rect (xpos-Floor(x/32))*32,(ypos-Floor(y/32))*32,32,32,False
	EndIf
	
	;palette
	For n=0 To 68
		tileno = n + tileoffset
		
		
		If activelayer <> 2
			If tileno<maxtile-1 Then DrawBlock tiles,((n-(Floor(n/23)*23))*32)+32,490+(Floor(n/23)*32),n+tileoffset
			Else
			If tileno<maxobject-1 Then DrawBlock objects,((n-(Floor(n/23)*23))*32)+32,490+(Floor(n/23)*32),n+tileoffset
		EndIf

		If tileno = activetile Then Color 0,255,0:Rect ((n-(Floor(n/23)*23))*32)+32,490+(Floor(n/23)*32),32,32,False

	Next
	
	
	tup=0
	If KeyDown(201) And tileoffset>0 And scrolldelay<0 Then tup=-1
	If KeyDown(209) And scrolldelay<0 Then tup=1
	;I know it looks like there is nothing in the quotes in the line below, but trust me, there is
	If (Button (0,490,32,"­",False,True)=True Or (mz = 1 And MouseOverTileset)) And tileoffset > 0 And scrolldelay<0 Then tup=-1
	If (Button (768,498,32,"¯",False,True)=True Or (mz = -1 And MouseOverTileset)) And scrolldelay<0 Then tup=1
	If KeyDown(82) And scrolldelay<0 Then activetile = activetile +1:scrolldelay=10
	If KeyDown(157) And scrolldelay<0 Then activetile = activetile -1:scrolldelay=10
	
	If tup<>0 Then tileoffset=tileoffset + (tup*23):scrolldelay=15

	If MouseOverTileset Then
		If MouseDown(1) Then 
			checktile = (Floor((MouseX()-32)/32))+(Floor((MouseY()-490)/32)*23)+tileoffset
			If (checktile < maxtile) And (checktile >-1) Then activetile = checktile
		EndIf 
	EndIf
	
	If Button(650,300,140,"Save") Then save("Test")
	If Button(650,320,140,"Load") Then load("Test")
	If Button(650,340,140,"Load Old") Then loadold("Test")
	Color 255,255,255
	Text 0,520,activetile
	
	
	DrawImage cursor,MouseX()-1,MouseY()-1
	Flip

Until KeyHit(1)
End
;END OF MAIN LOOP


Function drawmap(xpos,ypos,layer)

; sort out the block location based on pixel co-ord
xoff = Floor(xpos/32)
yoff = Floor(ypos/32)

; draw base layer
; uses draw block so you don't need a cls and is quicker.
If layer = 1
	For x = 0 To 19
		For y = 0 To 14
			If map(x+xoff,y+yoff,layer)>0 Then DrawBlock tiles,(x*32),(y*32),map(x+xoff,y+yoff,layer)-1
		Next
	Next
EndIf

If layer = 2
	For x = 0 To 19
		For y = 0 To 14
			If map(x+xoff,y+yoff,layer)>0 Then DrawImage objects,(x*32),(y*32),map(x+xoff,y+yoff,layer)-1
		Next
	Next
EndIf

; draw other layers
; draw image used so you get transparant sprites
If layer = 3
	For x = 0 To 19
		For y = 0 To 14
			If map(x+xoff,y+yoff,layer)>0 Then DrawImage tiles,(x*32),(y*32),map(x+xoff,y+yoff,layer)-1
		Next
	Next
EndIf

; layer 4, block overlay no transparancy
If layer = 4
	For x = 0 To 19
		For y = 0 To 14
			If map(x+xoff,y+yoff,layer)>0 Then DrawBlock tiles,(x*32),(y*32),map(x+xoff,y+yoff,layer)-1
		Next
	Next
EndIf

End Function


Function Button(x,y,width,name$,active=False, symbol=False)

	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) Then Color 200,200,200 Else Color 160,160,160
	Rect x,y,width,16
	Color 0,0,0

	If Symbol Then SetFont symbFont

	Text x+width/2,y+7,name,True,True

	If Symbol Then SetFont Font

	If active Then Color 255,0,0:Rect x,y,width,16,False
	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) And MouseDown(1) Then Return True Else Return False

End Function 



Function drawcollision(xpos,ypos)

; sort out the block location based on pixel co-ord
xoff = Floor(xpos/32)
yoff = Floor(ypos/32)
Color 255,0,0
For x=0 To 19
	For y=0 To 14
		If map(x+xoff,y+yoff,0)>0
			Rect (x*32)+8,(y*32)+8,16,16,False
			;Line x*32,y*32,x*32+31,y*32+31
			;Line x*32+31,y*32,x*32,y*32+31
		EndIf
	Next
Next

End Function



Function save(filename$)

fileout = WriteFile(filename+".map")
For layer = 0 To 4
	For x=0 To 255
		For y=0 To 255
			WriteInt(fileout,map(x,y,layer))
		Next
	Next
Next
CloseFile fileout

End Function

Function load(filename$)

filein = ReadFile(filename+".map")
For layer = 0 To 4
	For x=0 To 255
		For y=0 To 255
			map(x,y,layer)= ReadInt(filein)
		Next
	Next
Next
CloseFile filein

End Function

Function loadold(filename$)

filein = ReadFile(filename+".map")
For layer = 0 To 3
	For x=0 To 255
		For y=0 To 255
			map(x,y,layer)= ReadInt(filein)
		Next
	Next
Next

	For x=0 To 255
		For y=0 To 255
			map(x,y,4)= 0
		Next
	Next
CloseFile filein

End Function


looks good so far - but the alien.png in media ???

Guys,

Updated the firing code to use clips and bullets as is done in Alien Breed. Need to modify the following areas:

Type player
	Field name$
	Field x
	Field y
	Field frame
	Field clip
	Field ammo
	Field health
	Field fpause
	Field dir
	Field id
End Type


Function Player_Create.player(Name$,X%,Y%,id%)
	Local pl.player = New player
	
	pl\name = Name$
	pl\x = X
	pl\y = Y
	pl\frame = 0
	pl\health = 100
	pl\fpause = 0
	pl\dir = 0
	pl\id = id ; think this field could be made redundant-- but its there soo..
	;Ammo stuff
	pl\clip = 2
	pl\ammo = 15
	
	Return pl
End Function


In Function Player_UpdateAll():
	; collect objects
	If gettile(pl\x,pl\y,2)>0
		p.pickedup = New pickedup
		p\player = pl\id ; allowing for multiple players
		p\obj = gettile(pl\x,pl\y,2)
		;Determine what the player has collected
		If p\obj = 1 Then	;Ammo
		    If pl\ammo + 15 > 15 Then 
			pl\clip = pl\clip + 1
		    Else
			pl\ammo = pl\ammo + 15
		    End If
		End If
		puttile(pl\x,pl\y,2,0)
	EndIf


in 'temp hud to display objects collected' area (main loop in engine.bb):
For pl.player = Each player
    ammo$ = "C:" + RSet(pl\clip,2) + " A:" + RSet(pl\ammo,2)
	If pl\id = 1 Then Text 140, 0, ammo$
	If pl\id = 2 Then rText 500, 0, ammo$
Next


And finally:
Function shoot(p.player,angle,speed#)
	Local offset#=32.0
	
	;Check player can fire
	If p\clip > 0 Or p\ammo > 0 Then
		b.bullet=New bullet
		b\owner=p
		; add offset an position
		b\x=(p\x-GOffsetX)+Sin(angle)*offset
		b\y=(p\y-GOffsetY)+-Cos(angle)*offset		
		
		b\vx=Sin(angle)*speed
		b\vy=-Cos(angle)*speed
			
		; create muzzle flash
		
		;TODO: fire sound
		
		;Update clip and ammo count
		p\ammo = p\ammo - 1
		If p\ammo = 0 Then
                        p\ammo = 15
			;Update clip count
			p\clip = p\clip - 1
			If p\clip < 0 Then
				;Reset to nothing
				p\clip = 0
				p\ammo = 0
			End If
		End If
		
	Else
		;TODO: no fire - empty click sound
		
	End If
	
End Function


The method of collecting ammo will probably need to be tweaked a little to get it working just right.

Whoops... I cleverly uploaded the updated media as gfx.zip sorry! Deleted the old media.zip, renamed gfx.zip to media.zip, everything should be fine now.

Perturbatio, those look like good additions to the editor.
Matt, I'll add those bits in this evening.

Anyone want to have a go at aliens being shot?

I think we need to add a weapons type that handles weapon damage, weapon gfx, fire rate etc, and within the player type it needs a firedelay variable.

Just realised the:

handleblasts()
handlebullets()
update_aliens()

all need to be inside the timing loop after just after

GOffsetX=ScreenX
GOffsetY=ScreenY

Code Zip updated:

Added in the bits of code above so we've now got clips and ammo. Added an unlimited ammo cheat for testing!

Added the shooting of aliens, alien health and alien death.

Removed the offset from the blast and bullet positioning, all the offset is dealt with on the drawing part, this way every position stays world global rather than screen local.

History
02-09-2004 :	Perturbatio - Improved and fixed a couple of bugs in the editor
		Matt - Updated shooting and object collection to deal with clips
		Rob Farley - Removed offset from positioning of bullets and blasts
		             Added shooting of aliens, alien health and alien death

01-09-2004 :	Matt - Fixed the shooting bug
		Poed Boy - Seperated out the player code into functions and tidied up the main loop
		Rob Farley - Refixed the players getting stuck at edges bug!
		Rob Farley - Added alien gfx and basic alien handling code

31-08-2004 :	Rims - Blast and shooting includes (athough shooting appears to be a little buggy)
		Matt - Fixed players getting stuck at edges bug

29-08-2004 :	Rims - 2 Player code
		Rob Farley - Updated temp hud
		Rob Farley - Media, added block overlay on map, added object tiles.
		Rob Falrey - More Media, doors and keys now work. Door opening needs animation though
		Coffeedotbean kindly donated the media from his Alpha Breed project.

25-08-2004 :	Rob Farley - First release, basic map editor, game engine and tileset.


Looks good. I'm going to be away for a few days, so I won't be able to help. I'm annoyed about it, but I'll be back.

This was a good idea Rob, I'm learning quite a bit. It's also good to see a lot of things are commented so I know whats going on.

here's an updated weapons.bb. It adds weapon prototypes.
The player will need:
Field fireRate,tempFR
Field weapon.weapon
added.

weapons have:
x ammo, clips
x fire and out of ammo sounds
x damage
x fire rates (in ms)
x bullet speed

; functions added
x createWeapon(name$,etc)
x reloadPlayer(p.player)
x givePlayerAmmo(p.player,amount=15)
x getWeaponFromName.weapon(name$) ; case insensetive
x giveWeaponToPlayer(p.player,w.weapon) ; use above function
x deleteWeapons() ; for use at end of game
x fireWeapon(p.player,angle,force=0)

Bullets now have a damage from their weapon upon being fired. You can use this when aliens are hit with a bullet.


; weapons.bb by Rims

Type weapon
	Field name$
	Field maxClip,damage#
	Field ammo_in_a_clip
	Field bulletSpeed#
	Field fireRate ; in ms (passed to player when they get given the weapon)
	Field fireSoundChannel,fireSound
	Field outOfAmmoSoundChannel,outOfSound
	Field muzzleFlashImage
;	Field hud_image,pickUpImage
End Type

; create a weapon instance. We only need one. It's more of a prototype.
Function createWeapon.weapon(name$,damage#,maxc,aiac,rate,speed#,sound1$="",sound2$="")
	w.weapon=New weapon
	w\name=name
	w\damage=damage
	w\maxClip=maxc
	w\ammo_in_a_clip=aiac
	w\fireRate=rate
	w\bulletSpeed=speed
	If sound1<>""
		w\fireSound=LoadSound(sound1)
		; USE: w\fireSoundChannel=PlaySound(w\fireSound)
	EndIf
	If sound2<>""
		w\outOfSound=LoadSound(sound2)
	EndIf
	Return w
End Function		

Function reloadPlayer(p.player)
	If p = Null Then Return
	If p\clip=0 Then Return	
	p\clip=p\clip-1
	p\ammo=p\weapon\ammo_in_a_clip
End Function

Function givePlayerAmmo(p.player,amount=15)
	If p = Null Then Return
	If p\weapon=Null Then Return
	
	If p\ammo+amount >= p\weapon\ammo_in_a_clip
		p\Clip = p\Clip+1
		; if we've picked up a clip and we have no ammo, then load it automatically.
		If p\clip=1 And p\ammo=0 Then 
			reloadPlayer(p)
		EndIf
		; we can't have more clips than the weapon can allow.
		If p\weapon\maxClip <>-1
			; if the maxClip is -1 then you can hold an infinite number of clips
			If p\clip > p\weapon\maxClip Then p\clip=p\weapon\maxClip 
		EndIf
    Else
		p\ammo = p\ammo + amount
    EndIf	
End Function

Function getWeaponFromName.weapon(name$)
	name=Lower(name)
	For w.weapon=Each weapon
		If Lower(w\name)=name Then Return w
	Next
End Function	

Function giveWeaponToPlayer(p.player,w.weapon)
	If p = Null Then Return
	If w = Null Then Return
	p\weapon=w
	p\fireRate=p\weapon\fireRate
	p\tempFR = MilliSecs()
End Function

Function deleteWeapons()
	For i.weapon=Each weapon
		If i\fireSound<>0 Then FreeSound(i\fireSound)
		If i\outOfSound<>0 Then FreeSound(i\outOfSound)
		Delete i
	Next
End Function

; the force is here because if you use
; keydown() when shooting it will wait for the
; fireRate to time out. But if you use Keyhit()
; you'll want to override the fireRate timeout.
Function fireWeapon(p.player,angle,force=0)
	If p = Null Then Return
	If p\weapon = Null Then Return	
	
	; fire rate check
	If ((MilliSecs()-p\tempFR) > p\fireRate) Or force
		p\tempFR=MilliSecs()
		shoot(p,angle)
	EndIf
End Function
; --------------------------------


Type bullet
	Field x#,y#
	Field vx#,vy#
	Field owner.player
	Field life,damage#
End Type

Function shoot(p.player,angle)
	Local offset#=32.0
	
	speed#=p\weapon\bulletSpeed
		
	;Check player can fire
	If p\clip > 0 Or p\ammo > 0 Then
		b.bullet =New bullet
		b\owner = p
		b\damage=p\weapon\damage
		b\x=p\x+Sin(angle)*offset
		b\y=p\y-Cos(angle)*offset		
		
		b\vx=Sin(angle)*speed
		b\vy=-Cos(angle)*speed
			
		; create muzzle flash
		
		
		;TODO: fire sound
		p\weapon\fireSoundChannel=PlaySound(p\weapon\fireSound)
		
		;Update clip and ammo count
		If Not unlimited_ammo Then p\ammo = p\ammo - 1
		If p\ammo = 0 Then
			reloadPlayer(p) ; reload the player's weapon.
		EndIf
		
	Else
		;TODO: no fire - empty click sound
		p\weapon\outOfAmmoSoundChannel=PlaySound(p\weapon\outOfSound)
		
	End If
	
End Function

Function handleBullets()
	For b.bullet=Each bullet
		; each bullet has a damage from its parent weapon;
		; use b\damage when hitting aliens and stuff.
	
		ok=True		
		
		bx=b\x 
		by=b\y 
		
		If bx < 32 Then ok=False
		If by < 32 Then ok=False
		If bx > 7552 Then ok=False
		If by > 7552 Then ok=False
		
		If ok=True			
			result=gettile(b\x,b\y,0)
			If result
				; hit a wall. create a blast
	            blastHere(Rand(1,2),b\x-16,b\y-16,0.3)
				ok=False
			EndIf
			
			
			For al.alien = Each alien
				If circlesoverlap(al\x,al\y,alienradius,bx+16,by+16,3)
		            blastHere(Rand(1,2),b\x-16,b\y-16,0.3)
					alien_hit(al)
					ok=False
				EndIf
			Next
		EndIf
		
		b\x=(b\x+b\vx)
		b\y=(b\y+b\vy)		

		If ok=False Then Delete b
	Next	
End Function

Function drawBullets()
	Color 255,255,255
	For b.bullet=Each bullet
		bx=b\x-GOffsetX
		by=b\y-GOffsetY
		Rect bx,by,2,2
	Next	
End Function

create a weapon prototype like this:
; create the weapons we want in the game
;createWeapon.weapon(name$, damage#,maxClips, Ammo in a clip, fire rate, bullet speed#, fire sound1$="",out of ammo sound2$="")
createWeapon("machine gun",	1,5,100,100,3)

and give it to the player like this:
giveWeaponToPlayer(p.player,getWeaponFromName("machine gun"))

In player.bb, replace with this:
	; get input
	If pl=First player
		If KeyDown(205) And pl\x<7552 Then mr=True
		If KeyDown(203) And pl\x>0 Then ml=True
		If KeyDown(200) And pl\y>0 Then mu=True
		If KeyDown(208) And pl\y<7552 Then md=True
		
		If KeyDown(57)
			fireWeapon(pl,pl\dir*45,KeyHit(57))
		EndIf

	Else
		If KeyDown(32) And pl\x<7552 Then mr=True
		If KeyDown(30) And pl\x>0 Then ml=True
		If KeyDown(17) And pl\y>0 Then mu=True
		If KeyDown(31) And pl\y<7552 Then md=True
		If KeyDown(29)
			fireWeapon(pl,pl\dir*45,KeyHit(29))
		EndIf			
	EndIf

and this:
	; collect objects
	If gettile(pl\x,pl\y,2)>0

		;Determine what the player has collected
		; Don't add ammo to the collected list
		
		objcollect = gettile(pl\x,pl\y,2)
		
		If objcollect = 1 Then	;Ammo
			givePlayerAmmo(pl,15)
		Else		
			p.pickedup = New pickedup
			p\player = pl\id ; allowing for multiple players
			p\obj = objcollect				
		EndIf
		puttile(pl\x,pl\y,2,0)
	EndIf


Without looking through the code does this give different weapons different ammo? It doesn't look like it does.

I think different ammo for each weapon is pretty important, or indeed different weapons can share certain ammo.

Media and code zips updated:

04-09-2004 :	Rob Farley - Retreat/strafe mode, when holding down fire the played doesn't change direction
		           - Turnaround added so aliens and players don't switch from left to right they go round all available turning positions, makes it look better.
		           - Alien media tidied up a bit
		           - Bullet media added
			   - Alien blood media added
			   - When aliens dies they leave blood

03-09-2004 :	Rims - Different weapons
		Rob Farley - Different visible bullet types for the weapons, also this type is carried over to the kill_bullet to allow for different blasts depending on the bullet type
		           - Basic collision on the aliens so they don't run over each other, although they sometimes get stuck so this needs to be improved.

02-09-2004 :	Perturbatio - Improved and fixed a couple of bugs in the editor
		Matt - Updated shooting and object collection to deal with clips
		Rob Farley - Removed offset from positioning of bullets and blasts
		           - Added shooting of aliens, alien health and alien death

01-09-2004 :	Matt - Fixed the shooting bug
		Poed Boy - Seperated out the player code into functions and tidied up the main loop
		Rob Farley - Refixed the players getting stuck at edges bug!
		           - Added alien gfx and basic alien handling code

31-08-2004 :	Rims - Blast and shooting includes (athough shooting appears to be a little buggy)
		Matt - Fixed players getting stuck at edges bug

29-08-2004 :	Rims - 2 Player code
		Rob Farley - Updated temp hud
		           - Media, added block overlay on map, added object tiles.
		           - More Media, doors and keys now work. Door opening needs animation though
		Coffeedotbean kindly donated the media from his Alpha Breed project.

25-08-2004 :	Rob Farley - First release, basic map editor, game engine and tileset.


Come on guys... I'm feeling a bit left out here!

We need:
Graphics for the guns
Intex Systems, Media for the intex system consoles
Credits, credit media
Different door types so certain keys only open them
Improved alien AI
Player collision
Improved wall collision

Lets turn this into a game!

Whoop... Little bug in players.bb

		If objcollect = 1 Then	;Ammo
			givePlayerAmmo(pl,15)
			collectable = False
			puttile(pl\x,pl\y,2,0)
			EndIf


I'd just like to say awesome work dudes!
Fond memories of Team 17's Alien Breed and this is looking top banana! :)

Cheers and all the best,
Mikey F aka Clyde

Been away all weekend - will have a look at doing some stuff tomorrow night.

Got the amiga versions of Alien Breed and Tower Assult - will check out the gameplay etc and see what I can do. Maybe get some temp gfx as well if you want.

Hi Guys,

I noticed in the current version, the blood is tilebased so I went ahead and made a simple decal system. Now we can put it(and human blood, burn marks, guts, all the good stuff) anywhere and everywhere. I put real basic "splat" code in the alien hit and die functions. The splat graphics are just placeholders, but I think it does leave the impression of a hard fought, messier battle now. Hopefully someone will go all out with it later :D

I also did another small cleanup move. I moved the drawing loops for both aliens and players out of the main include into there respective includes( as "Player_DrawAll()" and "Alien_DrawAll()" ).

@Rob - Heres the zip( 12k ): http://users.adelphia.net/~tbarela/quicklink/AB_Decals.zip

- the decals folder for decal images goes in the gfx folder.
-"decals.bb" goes in the inc folder
- Replace "engine.bb","players.bb", and "aliens.bb" with the ones in the zip. They should be current up to the last bug fix you posted + the modifications I listed above.


a couple of questions:

1) Whats everyones thoughts on using a delta timed system? I know I'm probably asking this late(but better now then later), but we'd have better performance all around(at the expense of having to look at any movement and animation code we have).

2) Are we able to set down some coding guidelines? i.e. a naming scheme for variables and functions, history/code documenting requirements, etc.... Right now, there's not that much code, but further down the road it could become a big rats nest.

3) What are the "intex systems" ? I never played alienbreed before. (I've seen screens and read about it though) Can someone explain how they worked?

Just thought I'd add something.

Added gunflash on player, using the additional player frames.


Added 2 new type fields to player type, "IsFiring,IsFiringTimer"


Added to Player_UpdateAll() in players.bb after ;get input
If Firing=True
		If MilliSecs()>Pl\IsFiringTimer
			Pl\IsFiringTimer=MilliSecs()+25
			If Pl\IsFiring=True Then Pl\IsFiring=False Else Pl\IsFiring=True
		EndIf
	Else
		Pl\IsFiring=False
	EndIf



Added bit to the end of drawing player(s) in engine.bb - "+(Pl\IsFiring*120)"
For pl.player = Each player
	DrawImage playergfx,pl\x-32-ScreenX,pl\y-32-ScreenY,pl\frame+(pl\dir*15)+(Pl\IsFiring*120)
Next


POed, thanks for that, the blood splatter I did was just a quick thing anyway and I thought it looked a bit crappy, I haven't looked at your code yet but I was thinking that any splatter decals should probably have a timer on them too so they fade away after a certain time so we don't end up with hundreds of splatter decals all over the place. Also if it's timed it means every time an alien gets shot there could be splatter effects. I think this could probably be extended into a particle system of sorts, I think that'll be the easiest way to deal with any splatters or short term decals. As you could have a dead alien as a short term decal too, anyway, thoughts rambling through my mind here!

>>1) Whats everyones thoughts on using a delta timed system? I know I'm probably asking this late(but better now then later), but we'd have better performance all around(at the expense of having to look at any movement and animation code we have).

I've set the game logic to run at 120 updates per second so the frame rates can go upto 120fps. However, delta timing could be implemented pretty easily as the aliens currently move at .5 speed and players move at 1 speed. Animation frame could be based on xy position so that wouldn't be an issue

>>2) Are we able to set down some coding guidelines? i.e. a naming scheme for variables and functions, history/code documenting requirements, etc.... Right now, there's not that much code, but further down the road it could become a big rats nest.

Probably should!

>>3) What are the "intex systems" ? I never played alienbreed before. (I've seen screens and read about it though) Can someone explain how they worked?

Intex Systems were basically computer consoles that were shops, you could buy weapons, armour, ammo etc. So it's just a seperate screen that stops game play and allows players to upgrade.

I'll add these additions to the code a bit later and have a fresh version for the morning.

Coffee, any advice and/or pitfalls you have with alpha breed would be appreciated.

POed, thanks for that, the blood splatter I did was just a quick thing anyway and I thought it looked a bit crappy, I haven't looked at your code yet but I was thinking that any splatter decals should probably have a timer on them too so they fade away after a certain time so we don't end up with hundreds of splatter decals all over the place. Also if it's timed it means every time an alien gets shot there could be splatter effects. I think this could probably be extended into a particle system of sorts, I think that'll be the easiest way to deal with any splatters or short term decals. As you could have a dead alien as a short term decal too, anyway, thoughts rambling through my mind here!

Great minds think alike :D ? Check the notes in the decals include. Also, it's hardcoded right now, but the aliens do splat whilst being shot. Anyways, not really a useful post, just thought it was funny we were on the same brainwave ;)

Coffee, any advice and/or pitfalls you have with alpha breed would be appreciated.


I used Deltatimming for the final version (online version) and it work out fine.

I used A* for the aliens if they came within a certain radius of the player, else they moved about randomly.

My only pitfalls were slow downs when lots of enemies were on screen and using A*, but I simply only allowed 10 enemies to use A* at any 1 time.

The game is almost where I was with my version, cept a lightmapper. and editor written in B+.... still unsure about the strife fire... i much prefer the retreat fire in Alient breed.

When updating the aliens, perhaps we could check that each is within an adjacent area of the player, and if so they are then processed. If not, they not not updated.

The adjacent area might be 5-10 blocks outside the visible screen area. Might save some processing time?

I'm with coffee in regards to the retreat/straffing.

Matt, the alien check already does a distance check to the players before any "AI" kicks in so I don't think there's too much of over processing going on there.

The retreat/strafing thing was just an experiment, I think it's kinda cool except when you've got aliens behind you and you can't turn around... bloody annoying... So maybe have an extra button for the strafe/shoot and a regular shoot, I dunno, we'll see what happens.

Not got round to putting the code in yet (or indeed downloading it... I will defintatly do it tonight and have a go at cleaning up the code as it's getting messy again! Been very busy with real life stuff so difficult to keep up.

I'll probably have a go at writing the intex systems this evening as I think that'll be fun!

Something else that needs to be implemented are static animated objects (like the fans) so I'm thinking of adding an extra data layer to the map for this sort of thing, this would also be used for door types (red door, green door, if it needs a key etc) and probably amibient sound emitters etc. I think it'll be a useful addition.

Just found this... I think it'll be pretty handy for insipration at least...

http://www.ifrance.com/ninjaw/cd32/_AlienBreedTowerAssault/maps.html

I will start making some maps.

Some ideas:
-Aliens should not be able to see players when there is a wall between the aliens and the player.
- more alien splatterimages.

Snader, I wouldn't worry about making maps just yet (unless you really want to) as I'm not sure how much extra stuff will need to be added to the editor, as I said, I need to add an extra data layer.

I agree with your ideas.

ok, I've added a hud that looks like AB 1's. Here's the code for hud.bb:
You can get the hud image from here:

I've hardedcoded all the coords for drawing to 640x480, but could change it if you wanted to change res at a later date.
; simple hud
Global hud_block,hud_background,lives_block


Function setupHUD()
	hud_background=LoadImage("gfx\hud.png")
	; create block images on the fly
	hud_block=CreateImage(4,16)
	SetBuffer ImageBuffer(hud_block)
	Color 96,24,0 : Rect 0,0,4,2 : Rect 0,14,4,2
	Color 144,40,0: Rect 0,2,4,2 : Rect 0,12,4,2
	Color 180,84,0: Rect 0,4,4,2 : Rect 0,10,4,2
	Color 216,140,0:Rect 0,6,4,4
	SetBuffer BackBuffer()	

	; this'll have a green hue
	lives_block=CreateImage(4,16)
	SetBuffer ImageBuffer(lives_block)
	Color 0,96,24 : Rect 0,0,4,2 : Rect 0,14,4,2
	Color 0,144,40: Rect 0,2,4,2 : Rect 0,12,4,2
	Color 0,180,84: Rect 0,4,4,2 : Rect 0,10,4,2
	Color 0,216,140:Rect 0,6,4,4
	SetBuffer BackBuffer()	
End Function

Function drawHUD()
	vy=GraphicsHeight()-40

	; no transparency
	DrawBlock hud_background,0,vy
	
	; draw player lives, ammo and health
	For p.player=Each player
		;lives 
		If p=First player Then x=248 Else x=569
		y=0
		For i=1 To p\lives
			DrawBlock lives_block,x+(i*6),vy+y
		Next
	
		; health
		If p=First player Then x=62 Else x=382
		y=2
		For i=1 To p\health Step 3
			DrawBlock hud_block,x+((i/3)*4),vy+y
		Next		

		; clips
		If p=First player Then x=62 Else x=382
		y=24
		For i=1 To p\clip
			DrawBlock hud_block,(x+(i*5)),vy+y
		Next
		If p\clip > 5		
			Color 255,255,255
			; indicate we've got more than 5 clips with a plus '+'
			If p = First player Then Text 50,vy+16,"+" Else Text 211,vy+16,"+"
		EndIf

		; ammo
		If p=First player Then x=114 Else x=432
		y=24
		
		ammo=p\ammo
		clipSize=p\weapon\ammo_in_a_clip
		width#=(65/6)
		k#=(width/clipSize)*ammo
		
		For i=1 To k
			DrawBlock hud_block,x+(i*6),vy+y
		Next

		; keys
		y=18
		j1=0 : j2=0 ; count variables
		
		For pu.pickedup = Each pickedup			
			ok=True
			Select objectName(pu\obj)
				Case "Generic Key"	:frame=2
				Case "Red Key"		:frame=3
				Case "Green Key"	:frame=4
				Case "Blue Key"		:frame=5
				Default:			ok=False
			End Select
			; if ok=false then we're attempting to draw 
			; a pickedup object that isn't a key.
			; we only want to draw objects that are given
			; the ok by the above select.
			If ok
				If pu\player=1
					j1=j1+1
					Viewport 250,vy+y,55,20
					DrawImage Objects,(240+(10*j1)),vy+y,frame
					Viewport 0,0,GraphicsWidth(),GraphicsHeight()
				EndIf
				If pu\player=2
					j2=j2+1
					Viewport 570,vy+y,55,20
					DrawImage Objects,560+(10*j2),vy+y,frame
					Viewport 0,0,GraphicsWidth(),GraphicsHeight()
				EndIf
			EndIf					
		Next
	Next
	
End Function



Call setupHUD() to create/load images, etc.
and
drawHUD() instead of the bit at the end of the draw loop that draws the ammo and stuff.

I've added a "lives" field to the player and set it to 5 when the player is created in Player_Create.player(Name$,X%,Y%,id%)

I'm not sure about displaying the keys. See what you think by adding this piece of code:
; uncomment for a test of the player key HUD
If False
	; give the player five keys to test GUI.
	For u=3 To 5
		p.pickedup=New pickedup
		p\obj=u
		p\player=1
	Next
	p.pickedup=New pickedup
	p\obj=3
	p\player=1
	p.pickedup=New pickedup
	p\obj=3
	p\player=1	
EndIf

after
Type pickedup
	Field player
	Field obj
End Type
that bit.

Also, there's a mis-spelt 'firing' on line 127 of players.bb

Continues on this thread