CP - Alien Breed Remake - 5

Miscellaneous Forums/Blitz Showcase/CP - Alien Breed Remake - 5

http://www.perturbatio.com/files/AB/code.zip
http://www.perturbatio.com/files/AB/media.zip
http://www.perturbatio.com/files/AB/music.zip

Last Zip update: 2004-10-04 23:24:10 (Forum Time)





TODO:

Player, Alien clipping and accuracy
- improve collision detection with player/alien, bullet/alien, alien/player, alien/wall and player/wall.

Weapon Graphics
- For when you see them on the ground and pick em up! Also we need dead people decals! (see extend editor)

Different bad guys (need more, more!!!)
- Extend the Alien type to allow for different bad guys, including face huggers scuttling around and stuff. This would mean the radius needs to be included in the type and probably an offset variable so the image is drawn centrally, ie 64x64 would have an offset of 32 a 32x32 would have an offset of 16 etc.

Sound (partially done)
- There is some sound media in the original downloads from coffeedotbean but this needs to be implemented.

Ammo
- Needs to distiguish what weapons it's for

Intex system console
- Tiles for the intex systems so player can access it, this allows players to buy armour, weapons, ammo, health, etc. Maybe even sell stuff too?!

More Alien media
- Currently it's not animated, doesn't die etc etc. And if we made more than one alien too, also I think we need static bad guys too like auto cannons etc.

More Player media
- Personally I think we can cut half the animation frames out and you'd not notice, and use the spares for death and pain animation.
- More rotation animation?

Extend Editor (nearly/partially done)
-Need an object & script editor

Extend Scripting (basics in place)
- Need trigger code for 'onevery(n)' and 'onrandom(n,m)' and script support for createalien(), playsound(), animate()
for placing bad guy spawn points , ambient sounds, animated decals etc. (Mark Tiffany to progress code, feel free to create some animations).



Stickied already. That was fast :)

Rob,

I'm certainly happy to go with your Intex system as I thought it was pretty cool - that's one of the reasons I kept it seperate. Just wanted to do something that could be used - perhaps the framework could be hacked.

I guess everyone has been pretty busy - looking forward to getting back to regular updates!

With the current code and media I get errors that images do not exist...

mmm, the media needs to be updated with the latest intex images.

;Images 
Global intexBackground = LoadImage("gfx\intexbg.png")
Global intexFrame = LoadImage("gfx\intex-frame.png")
Global intexText = LoadAnimImage("gfx\intex-text-sm.png",8,11,0,40)
MaskImage intexText,255,0,255
;Global intexWeapon = LoadAnimImage("gfx\intex-weapons.png",320,88,0,6)
;MaskImage intexWeapon,255,0,255

Global bfont = LoadAnimImage("gfx\bitfnt.png",5,5,0,100)

Function btext(x,y,t$,hcentre=False,vcentre=False)
	If hcentre Then x=x-(Len(t)*3)
	If vcentre Then y=y-3
	For n=1 To Len(t)
		DrawImage bfont,x,y,Asc(Mid(t,n,1))-32
		x=x+6
	Next
End Function

Global intexChars$ = "*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:?"
Const pauseMax = 75
Const maxLines = 20
Const draw_char_delay_time=5

Const charWidth = 8
Const xOffset = 146
Const yOffset = 100

Type MenuSystem
	Field id
	Field build
	Field bChar
	Field bLine
	Field menuText$[maxLines]
	Field x[maxLines]
	Field y[maxLines]
	Field subMenu[maxLines]
	Field highlight[maxLines]
	Field total
	Field pauseCounter
	Field cursorRow
	Field cursorX
	Field cursorY
	Field bCharCounter
	
End Type

Global intexMenu.MenuSystem
Global gotr
Global gotg
Global gotb

Function GetRGB(image_name,x,y)
	argb=ReadPixelFast(x,y,ImageBuffer(image_name))
	gotr=(ARGB Shr 16) And $ff 
	gotg=(ARGB Shr 8) And $ff 
	gotb=ARGB And $ff
End Function


Function WriteRGB(image_name,x,y,red,green,blue)
	argb=(blue Or (green Shl 8) Or (red Shl 16) Or ($ff000000))
	WritePixelFast x,y,argb,ImageBuffer(image_name)
End Function

Function halfbright(source1,x1,y1,bias#)
	result = CreateImage(ImageWidth(source1),ImageHeight(source1))
	source2 = CreateImage(ImageWidth(source1),ImageHeight(source1))
	GrabImage source2,x1,y1	
	LockBuffer ImageBuffer(source1)
	LockBuffer ImageBuffer(source2)
	LockBuffer ImageBuffer(result)
	
	For x=0 To ImageWidth(source1)-1
		For y=0 To ImageHeight(source1)-1
		
			GetRGB(source1,x,y)
			r1#=gotr
			g1#=gotg
			b1#=gotb
			
			GetRGB(source2,x,y)
			r2#=gotr
			g2#=gotg
			b2#=gotb
			
			r3#=(r1*bias)+(r2*(1-bias))
			g3#=(g1*bias)+(g2*(1-bias))
			b3#=(b1*bias)+(b2*(1-bias))
			
			WriteRGB(result,x,y,r3,g3,b3)
			
		Next
	Next
	
	UnlockBuffer ImageBuffer(source1)
	UnlockBuffer ImageBuffer(source2)
	UnlockBuffer ImageBuffer(result)
	
	Return result
End Function
		


Function IntexMenu(pl.player)
	Local currentMenu = 0
	Local exitMenu = False
	Local preBootCounter = 0
	Local menuUpdateCounter
	
	;Create a menu store
	intexMenu.MenuSystem = New MenuSystem
	
	;Get the boot text
	GetMenuText(currentMenu,pl)
	
	ibg = halfbright(intexbackground,xoffset,yoffset,.8)
	
	
	While Not KeyHit(1) Or exitMenu = True
		;Set buffer
		SetBuffer BackBuffer()
		
		;Draw
		DrawBlock intexFrame,xOffset-15,yOffset-12
		DrawBlock ibg,xOffset,yOffset 
			
		;Drawtext
		ProcessMenuText()
		
		;Individual menu functions
		If intexMenu\build = False Or currentMenu = 11 Then
			Select currentMenu
				Case 0	;Intex Boot
					;Set menu to Main Menu 
					currentMenu = 1
					GetMenuText(currentMenu,pl)

				Case 1,2,3	;Main Menu
					DrawImage intexText,32+xOffset,intexMenu\y[intexMenu\highlight[intexMenu\cursorRow]], 0
					
					;Menu Up/Down
					If menuUpdateCounter = 0 Then
						If control(pUp,pl\id) And intexMenu\cursorRow > 1 Then
							intexMenu\cursorRow = intexMenu\cursorRow - 1
							menuUpdateCounter = 10
							
						ElseIf control(pDown,pl\id) And intexMenu\highlight[intexMenu\cursorRow + 1] <> 0 Then
							intexMenu\cursorRow = intexMenu\cursorRow + 1
							menuUpdateCounter = 10
							
						End If
						
					Else
						;Control the speed of the menu movement
						If menuUpdateCounter > 0 Then
							menuUpdateCounter = menuUpdateCounter - 1
						
						End If
						
					End If
					
					;Menu select
					If control(pfire1,pl\id) And intexMenu\subMenu[intexMenu\highlight[intexMenu\cursorRow]] > 0 Then
						currentMenu = intexMenu\subMenu[intexMenu\highlight[intexMenu\cursorRow]]
						GetMenuText(currentMenu,pl)
						
					End If
						
				Case 7
					If control(pfire1,pl\id) Then
						;Return to main menu
						currentMenu = 1
						GetMenuText(currentMenu,pl)
						
					End If
										
				Case 10	;Disconnect
					exitMenu = True
							
			End Select
			
		End If
		
		;Draw
		Flip True
		
	Wend
	
	;Clear keys
	FlushKeys()
	
	;Tidyup
	Delete Each menuSystem
	
End Function

Function GetMenuText(menu, pl.player)
	Local totalLines, lines
	Local lineText$, x, y, subMenu, max
	Local highlight

	Select menu
		Case 0	;Intex Boot
			Restore menuIntexBoot
			
		Case 1	;Menu
			Restore menuIntexMain

		Case 2	;Weapon Supplies
			Restore menuIntexWeaponsSupply
			
		Case 3	;Tool Supplies
			Restore menuIntexToolSupply
			
		Case 7	;Statistics
			Restore menuIntexStatistics
			
		Case 10	;Disconnect
			Restore menuIntexDisconnect
			
	End Select
	
	;Read the data
	Read totalLines
	
	;Clear
	For lines = 1 To maxLines
		intexMenu\highlight[lines] = 0
	Next
	
	;Process the lines
	For lines = 1 To totalLines
		Read lineText, x, y, subMenu, highlight
		intexMenu\menuText$[lines] = UpdateTags(Upper(lineText), pl)
		intexMenu\x[lines] = x/2 + xOffset
		intexMenu\y[lines] = y/2 + yOffset
		intexMenu\subMenu[lines] = subMenu
		
		;Set line selection
		If highlight <> -1 Then
			intexMenu\highlight[highlight] = Lines
			
		End If
		
	Next
	
	;Set remaining fields
	intexMenu\build = True
	intexMenu\bChar = 0
	intexMenu\bLine = 1
	intexMenu\id = menu
	intexMenu\pauseCounter = 0
	intexMenu\total = totalLines + 1
	intexMenu\cursorRow = 1
	intexMenu\bCharCounter = 0
	
End Function

Function UpdateTags$(lineText$, pl.player)
	;Update tags
	lineText = Replace(lineText,"%PLSCORE%",LSet(pl\score,6))
	lineText = Replace(lineText,"%PLCREDITS%",LSet(pl\credits,6))
	lineText = Replace(lineText,"%PLKILLS%",pl\kills)
	lineText = Replace(lineText,"%PLSHOTS%",LSet(pl\shots,6))
	lineText = Replace(lineText,"%PLDOORS%",LSet(pl\doors,6))
	lineText = Replace(lineText,"%PLAMMO%",LSet(pl\clip,6))
	lineText = Replace(lineText,"%PLENERGY%","GOOD")
	lineText = Replace(lineText,"%PLCURRENTWEAPON%",Upper(pl\weapon\name))	;Current
	lineText = Replace(lineText,"%WBROADHURST%",WeaponStatus(pl\ownedWeapons[1]))
	lineText = Replace(lineText,"%WDALTON%",WeaponStatus(pl\ownedWeapons[2]))
	lineText = Replace(lineText,"%WROBINSON%",WeaponStatus(pl\ownedWeapons[3]))
	lineText = Replace(lineText,"%WRYXX%",WeaponStatus(pl\ownedWeapons[4]))
	lineText = Replace(lineText,"%WSTYRLING%",WeaponStatus(pl\ownedWeapons[5]))
	lineText = Replace(lineText,"%WIMPACT%",WeaponStatus(pl\ownedWeapons[6]))

	;Return
	Return lineText
	
End Function

Function WeaponStatus$(wp.weapon)
	If wp<>Null Then
		Return "YES"
		
	End If
	Return " NO"
End Function

Function ProcessMenuText()
	Local currentChar$,x,y,maxChar,char
	Local charCounter = 0
	Local drawCursor = False
	
	If intexMenu\build Then
		If intexMenu\bChar > 0 Then
			;Get the current char
			Repeat
				currentChar = Mid(intexMenu\menuText[intexMenu\bLine],intexMenu\bChar,1)
				If currentChar = " " And intexMenu\bChar < Len(intexMenu\menuText[intexMenu\bLine]) - 1 Then
					;Skip over any spaces
					intexMenu\bCharCounter = intexMenu\bCharCounter + 1
					intexMenu\bChar = intexMenu\bChar + 1
					
				ElseIf currentChar = "+" Then
					;We need to pause
					intexMenu\pauseCounter = (intexMenu\pauseCounter +1) Mod pauseMax
				    Exit
				    
				Else
					;Exit out
					Exit
					
			    End If
			    			    
		    Forever
			
		End If
		
		;Continue to process text
		If intexMenu\pauseCounter = 0 Then
			;Increment number of shown characters
			intexMenu\bCharCounter = intexMenu\bCharCounter + 1
			
			;Increment char
			intexMenu\bChar = (intexMenu\bChar + 1) Mod Len(intexMenu\menuText[intexMenu\bLine])
			If intexMenu\bChar = 0 Then
				;Increment line
				intexMenu\bLine = (intexMenu\bLine + 1) Mod intexMenu\total
				If intexMenu\bLine = 0 Then
					;Set each item to it's max
					intexMenu\bLine = intexMenu\total - 1
					intexMenu\bChar = Len(intexMenu\menuText[intexMenu\bLine])
					
					;Finish
					intexMenu\build = False
					FlushKeys()
					
				End If
				
			End If
			
		End If
		
	End If
	
	;Draw text
	For drawLine = 1 To intexMenu\bLine
		;Set co-ords for current line
		x = intexMenu\x[drawLine]
		y = intexMenu\y[drawLine]
			
		;Draw current line
		For drawChar = 1 To Len(intexMenu\menuText[drawLine])
			;Increment letter count
			charCounter = charCounter + 1
			
			;Get current char
			char = Instr(intexChars, Mid(intexMenu\menuText[drawLine],drawChar,1)) - 1
			If char > -1 Then
				DrawImage intexText,x,y,char
			
			End If
			
			;Building the menu, if so pause on last char and display cursor
			If intexMenu\build Then
				;Slight pause when first displaying character?
				If (charCounter = intexMenu\bCharCounter) Then 
					Delay draw_char_delay_time
					intexMenu\cursorX = x
					intexMenu\cursory = y
					drawCursor = True
					Exit
				
				End If
					
			End If
			
			x = x + charWidth
			
		Next
			
		If drawCursor Then
			DrawImage intexText,intexMenu\cursorX,intexMenu\cursorY,0
			Exit
			
		End If
		
	Next
	
End Function

;Data Structure
;No of lines
;Text$,X,Y,SubMenu

.menuIntexBoot
Data 10
Data "INTEX NETWORK CONNECT: CODE ABF01DCC60 ",8,96,-1,-1
Data "CONNECTING..................... ",8,120,-1,-1
Data "INTEX NETWORK SYSTEM V10.0 ",8,168,-1,-1
Data "2G RAM:           OK ",8,192,-1,-1
Data "EXTERNAL DEVICE:  OK ",8,216,-1,-1
Data "SYSTEM V1.10 CS:  OK ",8,240,-1,-1
Data "VIDEODISPLAY:     DAMAGED+ ",8,264,-1,-1
Data "EXECUTING DOS 5.0 ",8,312,-1,-1
Data "SYSTEM DOWNLOADING NETWORKDATA..... OK ",8,336,-1,-1
Data "INTEX EXECUTED!+ ",8,360,-1,-1

.menuIntexMain
Data 8
Data "INTEX MAIN MENU ",192,64,-1,-1
Data "INTEX WEAPON SUPPLIES ",144,136,-1,1
Data "INTEX TOOL SUPPLIES ",160,160,3,2
Data "INTEX RADAR SERVICE ",160,184,-1,3
Data "LEVEL INFORMATION UPDATE ",128,208,-1,4
Data "INTEX ENTERTAINMENT ",160,232,-1,5
Data "STATISTICS ",240,256,7,6
Data "EXIT INTEX NETWORK ",176,280,10,7

.menuIntexWeaponsSupply
Data 2
Data "INTEX WEAPON SUPPLIES ",144,48,-1,-1
Data "WEAPON SUPPLIES REQUEST: ",48,96,-1,-1

.menuIntexToolSupply
Data 8
Data "INTEX TOOL SUPPLIES ",160,72,-1,-1
Data "ELECTRONIC HAND MAP        500 CR ",64,144,-1,1 
Data "AMMO NYBBLE               1000 CR ",64,192,-1,2
Data "FIRST AID KIT             2000 CR ",64,240,-1,3
Data "6 KEYS                    4000 CR ",64,288,-1,4
Data "EXTRA LIFE               10000 CR ",64,336,-1,5
Data "EXIT ",288,384,1,6
Data "YOUR CREDIT LIMIT IS: %PLCREDITS% CR ",80,432,-1,-1

.menuIntexStatistics
Data 16
Data "INTEX STATISTICS ",176,32,-1,-1
Data "PLAYER SCORES:  %PLSCORE% PTS ",80,80,-1,-1
Data "ALIENS KILLED:  %PLKILLS% ",80,104,-1,-1
Data "SHOTS FIRED:  %PLSHOTS% BULLETS ",112,128,-1,-1
Data "CREDITS OWNED:  %PLCREDITS% CR ",80,152,-1,-1
Data "DOORS OPENED:  %PLDOORS% ",96,176,-1,-1
Data "AMMO OWNED:  %PLAMMO% CLIP",128,200,-1,-1
Data "ENERGY STATE:  %PLENERGY% ",96,224,-1,-1
Data "CURRENT WEAPON:  %PLCURRENTWEAPON%",64,248,-1,-1
Data "WEAPONS AVAILABLE: ",16,272,-1,-1
Data weaponBroadhurst + "... %WBROADHURST% ",48,320,-1,-1		;112
Data weaponDalton + "...           %WDALTON% ",48,344,-1,-1
Data weaponRobinson + "...        %WROBINSON% ",48,368,-1,-1
Data weaponRyxx + "...         %WRYXX% ",48,392,-1,-1
Data weaponStyrling + "...        %WSTYRLING% ",48,416,-1,-1
Data weaponImpact + "...    %WIMPACT% ",48,440,-1,-1

.menuIntexDisconnect
Data 1
Data "DISCONNECTING..............+ ",32,128,-1,-1


Updated intex system so it's a bit flashier!

Sent email to Pert with new intex background media.

new media.zip is being uploaded as we speak, also can get the new graphic here


Different bad guys (need more, more!!!)
- Extend the Alien type to allow for different bad guys, including face huggers scuttling around and stuff. This would mean the radius needs to be included in the type and probably an offset variable so the image is drawn centrally, ie 64x64 would have an offset of 32 a 32x32 would have an offset of 16 etc.



ImageHeight() and/or ImageWidth() should sort that no problem. Also allowing you to have non-square images

New particles.bb this gives each particle an order so particles can be drawn above or below the action. This fixes a bugette introduced to make blood be drawn after the players. The problem with this is that alien blood splats float above players too... not ideal. Anyway... New particles.bb

Createparticle now has an extra parameter of order that defaults to 1 (above the action)
Global particles = LoadAnimImage("gfx\particles\particles.png",32,32,0,4)
MaskImage particles,255,0,255
Global alienblood = LoadAnimImage("gfx\particles\splatfade.png",64,64,0,8)
MaskImage alienblood,255,0,255

Type particle
	Field x#,y#,xs#,ys#
	Field firstframe,lastframe
	Field life
	Field totallife
	Field offset
	Field graphic
	Field order
End Type

Global maxparticle = 200
Global particlecount = 0

Function createparticle(x,y,xs#,ys#,life,firstframe,lastframe,graphic,offset,order=1)

; x,y - the particle position
; xs,ys - the particle speed
; life - how long it will last
; graphic - what graphic to use
; offset - how much it should offset when drawing ie a 32x32 particle would have a 16 offset

; the animation will play from beginning to end over the life of the particle

	Local p.particle = New particle
	
	p\x = x
	p\y = y
	p\xs = xs
	p\ys = ys
	p\life = life
	p\totallife = life
	p\firstframe = firstframe
	p\lastframe = lastframe
	p\graphic = graphic
	p\offset = offset
	p\order = order
	
End Function

Function UpdateParticles()

	If particlecount>maxparticle Then Delete First particle

	particlecount = 0
	
	Local p.particle
	
	For p = Each particle
		
		; move the particle
		p\x = p\x + p\xs
		p\y = p\y + p\ys
		
		; dampen the speed
		p\xs = p\xs * .9
		p\ys = p\ys * .9

		; particle hits the wall
		result=gettile(p\x,p\y,LayerCollision)
		If result
			;p\life=-1 ; kill me
			; no, bounce back actually
			p\xs=-p\xs*0.2
			p\ys=-p\ys*0.2
		EndIf
		
		; reduce the life
		p\life = p\life - 1
		If p\life <= 0 Then Delete p Else particlecount=particlecount+1
	Next
End Function
	
	
Function drawparticles(order)
	
	Local p.particle
	
	For p = Each particle
	
		If p\order = order
			; work out what frame it should be displaying
			range = p\lastframe - p\firstframe
			life# = Float(p\totallife - p\life) / Float(p\totallife)
			frame = range * life
			frame = p\firstframe+frame
			
			DrawImage p\graphic,p\x-p\offset-ScreenX,p\y-p\offset-ScreenY,frame
		EndIf
		
	Next
End Function


Also a bit of engine.bb has been updated to take into account the order of particle drawing....

As you can see with this drawparticles now has an order number sent to it. When you create a particle it defaults to order 1 (above the action) so if you want bloodsplats after something dies then you'd give it an order of 0. (see above)

	; ********* RENDER WORLD		
	drawmap(ScreenX,ScreenY,1)
	drawparticles(0)
	drawmap(ScreenX,ScreenY,2)
	drawbullets()
	Alien_DrawAll()
	Player_DrawAll()
	drawAnimations()
	drawparticles(1)
	drawmap(ScreenX,ScreenY,3)
	drawmap(ScreenX,ScreenY,4)
	drawHUD()
	; end of render


Also aliens.bb needed to be updated to set the blood splat order to 0 (note: this is just the alien_die function)

Also whilst I was about it I made it so the face huggers leave a smaller blood splatter than the big guys.
Function Alien_Die(al.alien)
	
	If al\kind = 0 Then createparticle(al\x,al\y,0,0,1000,0,7,alienblood,32,0)
	If al\kind = 1 Then createparticle(al\x,al\y,0,0,500,3,7,alienblood,32,0)
	playoneshot(snd_aliendeath,al\x,al\y)
	
	;create death splat
	n=Rand(20)+5
	For i=1 To n
		d=Rand(359)
		f=Rand(0,3)
		createparticle(al\x,al\y,Sin(d)*2,Cos(d)*2,Rand(10,100),f,f,particles,16)	
	Next
	
	Delete al.alien
			
End Function


I've sent Perty a new code.zip and new image for the objects. I've added the onLoad and OnEvery to the scripting. I've added some default things in the objects.png such as:
www.3030deathwar.co.uk/downloads/ab/objects.png
- Spawn an alien on load
- Spawn a hugger on load
- Spawn an alien every 10 seconds
- Spawn an alien every 30 seconds
- Spawn a hugger every 10 seconds
- Spawn a hugger every 30 seconds
(These are just examples I've implemented to show you what they do)

I'll do the player start and intex system interaction now

ouch. Here's another update. I suspect I've still got a tiny bit of bandwidth...

- Added player start points (add them in the editor)
- Added action button. Stand near (see below) an intex terminal to use it. Key = return

Here's the new objects.png, www.3030deathwar.co.uk/downloads/ab/objects.png

Also, the code.zip: www.3030deathwar.co.uk/downloads/ab/code.zip

------------------
I've checked around you for an action, so:
  []
[][][]
  []

will be checked as you can't stand ON an intex terminal. Only problem is we have to keep onAction things at least 2 tiles awat from each other to keep from confusing this function. It might try and run the wrong one.

I'm having ftp trouble at the moment, I may have to wait until tomorrow to try again.

Rims, why not check the onaction stuff based on what square you're heading for?

Check the tile location under the current x,y (x/32 , y/32) then do a check of the tile location where the player is headed (x+1 / 32,y /32) then if these tile locations are different do a gettile for the onaction stuff.

zips updated

What's everyone working on at the moment? I can see us working hard on something and when the times comes to update find out that someone else has done that bit... but better.

I'm working on scripting at the moment.

Doing graphics here

I've been messing around with the GUI, thinking about doing a listbox component.

Don't know if this will help, it's from my own gui thingy. You send the options as a | seperated list. No scrolling though.

Function list(x,y,width,height,options$,value)
Color 210,210,210
Rect x,y,width,height,True

Color clip(gui_r-gui_contrast),clip(gui_g-gui_contrast),clip(gui_b-gui_contrast)
Line x,y,x+width,y
Line x,y,x,y+height
Color clip(gui_r+gui_contrast),clip(gui_g+gui_contrast),clip(gui_b+gui_contrast)
Line x+width,y,x+width,y+height
Line x,y+height,x+width,y+height

Color 0,0,0
Viewport x,y,width,height

ret_value=-1
			yy=0
			pos=1
			selection=0
			Repeat
				comma=Instr(options,"|",pos)
				v$=Mid$(options,pos,comma-pos)
				If selection=value Then Color 150,150,150:Rect x+1,(y+1)+yy,width-1,16,True
				
				Color 0,0,0
				If RectsOverlap (x+1,(y+1)+yy,width-1,14,MouseX(),MouseY(),1,1) And RectsOverlap (x,y,width,height,MouseX(),MouseY(),1,1)
					Rect x+1,(y+1)+yy,width-1,16,True
					Color 210,210,210
					If MouseDown(1) Then ret_value=selection:gui_click=True
					EndIf
				Text x+4,(y+2)+yy,v$	
				pos=comma+1
				yy=yy+14
				selection=selection+1
				Until comma=0

Viewport 0,0,GraphicsWidth(),GraphicsHeight()				
If ret_value>-1 Then Return ret_value Else Return value

End Function


I was experimenting with the graphics and I thought these intex-objecttiles would be nice. I made these because I thought that the former ones didn't look that good in Fullscreen.



Also the AMMO object was altered a bit by me...

I'm off to New Zealand for the next month so, good luck to you all!

First new alien... 8 frames of animation, 16 rotations. I know this can't be added at the moment, but this is what I'm working on at the moment. Creating or lifting 3D models and turing them into sprites. This was my first attempt using the caustic md3 from polycount, I had to import it into milkshape, bone it, pose it, then animate it. Saved it out as a b3d, then wrote a little program to render the frames and rotations.

.

it would be nice to have a couple of spawn animations.
maybe burst from the floor and wall animations.

*EDIT*

not that I'm knocking what you've done so far, it looks good :)

Quick suggestion, could you maybe [edit] the first post in the thread to include the date/time the zips were last updated..?

.

With these new player graphics we should be able to get to some weapon graphics soon. We'll just overlay and offset the guns rotations in-line with the player's graphics then draw the weapon over. It'll look very nice. Nice graphics by the way, Rob.

I've messed something up somewhere! Getting there though! Anyone care to take a look... it's late and I'm tired.

Players.bb

I've changed the way the control is handled to deal with any direction, however, now I get a runtime error when you try to open the door. And not got the collision stuff 100% yet, however, once I've got this bit working it'll work really well for alien ai and stuff. (Incedenally no idea what the aliens will be doing once you get through the door as I've not fixed aliens.bb yet.)

I've added a speed type to the player so we can have faster or slower players (for different player classes in the future). Made the x y coods floats to deal with the speeds correctly and angle direction correctly.

Updated the animation, removed the firing flash.

[code removed as I've fixed it below]

Um... Yeah, I think that's it for the time being, if anyone wants to take a look at this and try and sort out where I've gone wrong please do...

Time for bed said zeberdee...


Utils dirdif function updated to deal with 16 frames of rotation rather than 8
Function dirdif(angle1,angle2) 

a= ((angle2 - angle1) Mod 16 + 24) Mod 16 - 8 
If a<0 Then a=-1
If a>0 Then a=1
angle1 = angle1 + a
If angle1>15 Then angle1=0
If angle1<0 Then angle1=15

Return angle1
End Function


Ok, I've almost got the listbox working as a dialogue, it gets a lot more complicated when allowing other things to continue along side it.

new include stringlist.bb:
; Use a reasonably large number to limit the number 
; of lines that a stringlist can contain
Const MaxStringListSize = 512

Type TStringItem
	Field FString$
	Field FObject%
	Field FUsed = False
End Type

Type TStringList
	Field FItems.TStringItem[MaxStringListSize]
	Field FCount
End Type


;CONSTRUCTOR;
;;;;;;;;;;;;;;;;;;;
; FUNCTION Create ;
;;;;;;;;;;;;;;;;;;;
Function Create.TStringList()
	Local sList.TStringList = New TStringList
	;can add any initialization code here so that all new stringlists
	;start with the same values
	For t = 0 To MaxStringListSize
		sList\FItems.TStringItem[t] = New TStringItem
	Next
	Return sList
End Function



;DESTRUCTOR;
;;;;;;;;;;;;;;;;;;;;
; FUNCTION Destroy ;
;;;;;;;;;;;;;;;;;;;;
Function Destroy(sList.TStringList)
	For t = 0 To MaxStringListSize
		Delete sList\FItems[t]
	Next
	Delete sList
End Function



;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetText ;
;;;;;;;;;;;;;;;;;;;;
;returns all the items as one single string
Function GetText$(sList.TStringList)
;VARS
	Local result$ = ""
	
;MAIN
	For i = 0 To GetCount(sList)
		result$ = result$ + sList\FItems[i]\FString$
	Next

	Return result$
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION Strings                                     ;
; return the string of the item at the specified index ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function Strings$(sList.TStringList, Index%)
	Return sList\FItems[Index]\FString$
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION AddItem                                          ;
; if index > -1 then insert the item at the specified index ;
; will return the index the item is added at.               ;
; if the return value is <0 then an error has occured       ;
; (probably exceeded MaxStringListSize)                     ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function AddItem(sList.TStringList, txt$, Obj%=0, Index%=-1)
	Local result = -1 ;set the default result to a failure, only a success will change this
	Local Count = GetCount(sList)
	
	If Index >  MaxStringListSize Then Return -1
	If Count => MaxStringListSize Then Return -1
	
	If Index < 0 Then ;add to the end
		sList\FItems[Count]\FString$ = txt$
		sList\FItems[Count]\FObject% = Obj%
		sList\FItems[Count]\FUsed    = True
		result = Count
	Else
		For i = Count To Index + 1 Step -1
			sList\FItems[i]\FString$ = sList\FItems[i-1]\FString$
			sList\FItems[i]\FObject% = sList\FItems[i-1]\FObject%
			sList\FItems[i]\FUsed    = sList\FItems[i-1]\FUsed
		Next
		
		sList\FItems[Index]\FString$ = txt$
		sList\FItems[Index]\FObject% = Obj%
		sList\FItems[Index]\FUsed    = True

		result = Index
	EndIf

GetCount(sList)

Return result

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION DeleteItem                      ;
; Delete the line with the specified index ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function DeleteItem(sList.TStringList, Index%)
	;If the index passed is out of bounds then leave the function
	If (index < 0) Or (Index > MaxStringListSize) Then Return

	If Index < MaxStringListSize Then
		For i = Index To MaxStringListSize-1
			If i < MaxStringListSize Then
				sList\FItems[i]\FString$ = sList\FItems[i+1]\FString$
				sList\FItems[i]\FObject% = sList\FItems[i+1]\FObject%
				sList\FItems[i]\FUsed = sList\FItems[i+1]\FUsed
			EndIf
			;clear the next line, this will result in the last line not being used

				sList\FItems[i+1]\FString$ = ""
				sList\FItems[i+1]\FObject% = 0
				sList\FItems[i+1]\FUsed    = False
			;EndIf
		Next
	Else ;if the Index is equal to the MaxStringListSize then just clear it
		sList\FItems[Index]\FString$ = ""
		sList\FItems[Index]\FObject% = 0
		sList\FItems[Index]\FUsed = False
	EndIf

GetCount(sList)

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetCount                   ;
; Returns the number of items         ;
; in the list (Not THE HIGHEST INDEX) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function GetCount(sList.TStringList)
;VARS
	Local Used = 1
	Local Count = 0
;MAIN

	While (Used <> 0) And (Count < MaxStringListSize)
		Used = sList\FItems[Count]\FUsed	
		If used Then Count = Count + 1
	Wend
	
	sList\FCount = Count
	
	Return sList\FCount
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;TEST;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Print Getcount(sl)
;AddItem(sl,"Third Line of Text" + Chr$(13))
;Print Getcount(sl)
;AddItem(sl,"Fourth Line of Text")
;Print Getcount(sl)
;Print GetText(sl)
;DeleteItem(sl,0)
;Print GetText(sl)
;Print Getcount(sl)
;Print strings(sl,2)
;Print GetText(sl)
;
;AddItem(sl,"New Line inserted at 1",0,1)
;
;
;Print Str(sl)
;For i = 0 To GetCount(sl)-1
;	Print Strings(sl,i)
;Next
;
;Destroy sl
;
;Print Str(sl)
;
;WaitKey()
;End


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

Include "inc\stringlist.bb"
Dim CharWidths(1)

Const KeyRepeat% = 100
Const CaratSymbol$ = "¦"

Type TRGB
	Field ColRed%
	Field ColGreen%
	Field ColBlue%
End Type


Global myRGB.TRGB = New TRGB

Type TCarat
	;X and Y in characters not pixels
	Field X%
	Field Y%
	Field PX%
	Field PY%
	Field Symbol$ = "¦"
End Type

Type TKeyState
	Field Scancode%
	Field Ascii%
	Field Shift
	Field Ctrl
End Type


Type TLine
	Field LineNum%
	Field Txt$
	Field Owner$
End Type


;;;;;;;;;;;;;;;;;;;;
; FUNCTION InitGUI ;
;;;;;;;;;;;;;;;;;;;;
Function InitGUI()

	SetFont font

;INPUT BOX SETUP
;Get the character widths
Dim charwidths(512)
	charwidths(32) = 4
	For c = 33 To 512
		charwidths(c) = StringWidth(Chr$(c))
	Next
End Function


;;;;;;;;;;;;;;;;;;;
; FUNCTION Button ;
;;;;;;;;;;;;;;;;;;;

Function Button(x,y,width,name$,active=False, symbol=False, ShortCutKey=KEY_NONE, ShowShortCut = True, OffCol%=$A0A0A0,  OverCol%=$C8C8C8, TextCol%=$000000)
;VARS
	Local result = False
	
;MAIN
	
	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) Then 
		myRGB = GetRGB(OverCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
	Else 
		myRGB = GetRGB(OffCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
	EndIf
	Rect x,y,width,16

	myRGB = GetRGB(TextCol)
	Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue


	If Symbol Then SetFont symbFont

	If (ShortCutKey > KEY_NONE) And (ShowShortCut) Then name = name + " ("+ KeyNames(ShortCutKey) +")"

	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 result = True

	If ShortCutKey > KEY_NONE Then
		If KeyDown(ShortCutKey) Then Result = True
	EndIf

	Return Result
	
End Function 



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION InputBox									 ;
; Parameters:                                        ;
; msg$ : any message to display above the input box  ;
; x,y : top left coords                              ;
; width, height: outer width and height of inputbox  ;
; rtnSubmit : if the return key is pressed, then     ;
;             automatically submit the text			 ;
;             If this is false, then an OK button is ;
;             displayed at the bottom of the box     ;
; DefaultText : automatically inserts this into the  ;
; input box, the carat will be positioned at the end ;
; of this text.                                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function InputBox$(Msg$,x,y,width,height,rtnSubmit=True, DefaultText$="", BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)

	SetFont Font

;;;;;;
;vars;
;;;;;;

	Local leave = False
	Local InnerWidth = Width - 6
	Local InnerHeight = Height - 40
	Local InnerX = 6
	Local InnerY = 20
	Local retString$ = ""
	Local fntWidth = FontWidth()/4
	Local fntHeight = FontHeight()
	Local EditWin = CreateImage(width, height)
	Local Delimiters$ = "|() "+Chr$(13)
	Local FoundDelim = False
	Local TopLine = 0
	
	Local Carat.TCarat = New TCarat
			Carat\X = 0
			Carat\Y = 0

	Local SelStart% = 0 
	Local SelEnd% = 0
	Local CaratPos% = 0
	
	Local ScrollPos = 0
	
	Local ScrollWidth = 12

;;;;;;
;main;
;;;;;;

If rtnSubmit Then InnerHeight = Height - 6
FlushKeys()
CaratPos = Len(DefaultText)
retString = retString+DefaultText

Repeat
	;quit the function without returning any text if escape is pressed
	If KeyHit(1) Then 
		leave = True
		retString$ = ""
	EndIf
	
	;;;;;;;;;;;;;;;;;;;;;
	;get character input;
	;;;;;;;;;;;;;;;;;;;;;
	get = GetKey()
	
	
	
	If Get = 13 Then
		If rtnSubmit Then 
			leave = True ;if return is pressed and rtnSubmit is True then leave
		Else
			LeftSide$ = Left$(retString$,CaratPos)
			RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
			retString$ = LeftSide$ + Chr(get) + RightSide$
			CaratPos = CaratPos + 1
		EndIf
	ElseIf KeyDown(14); backspace
		If MilliSecs()-LastInput > KeyRepeat Then
			If Len(retString$) > 0 Then 
				LeftSide$ = Left$(retString$,CaratPos)
				RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
				retString$ = Left$(LeftSide$, Len(LeftSide$) -1) + RightSide$
			EndIf
			LastInput = MilliSecs()
			CaratPos = CaratPos - 1
			If CaratPos < 0 Then CaratPos = 0
		EndIf
	ElseIf KeyDown(203) ;Left Cursor
		If MilliSecs()-LastInput > KeyRepeat Then
		
			If KeyDown(157) ; CTRL ; Allow CTRL+Left to jump the carat pos to the next delimiter to the left of the cursor
				For i = CaratPos To 1 Step -1
					
					d = 1
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )	
						
						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i-1
							FoundDelim = True
						EndIf
						d = d + 1
					
					Wend
				
					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
				
				FoundDelim = False
			
			Else
				CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
			EndIf
			LastInput = MilliSecs()
		EndIf
	ElseIf KeyDown(205) ; RIGHT CURSOR
		If MilliSecs()-LastInput > KeyRepeat Then
			If KeyDown(157) ;CTRL ; Allow CTRL+RIGHT to jump the carat pos to the next delimiter to the right of the cursor

				For i = CaratPos+1 To Len(retString$)
					d = 1					
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )

						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i
							FoundDelim = True
						EndIf
						d = d + 1
					Wend				

					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
				
				FoundDelim = False
		
			Else
				CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
			EndIf
			LastInput = MilliSecs()
		EndIf

	ElseIf KeyDown(207) ; end
		CaratPos = Len(retString$)
	ElseIf KeyDown(199) ; home
		CaratPos = 0
	ElseIf (get > 31) ;is a letter, number or symbol

		LeftSide$ = Left$(retString$,CaratPos)
		RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
		retString$ = LeftSide$ + Chr(get) + RightSide$
		CaratPos = CaratPos + 1
		
	EndIf

		
		;Draw the edit window
		oldbuffer = GraphicsBuffer()
		SetBuffer ImageBuffer(EditWin)
			
			myRGB = GetRGB(BorderCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 0,0,width,height

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 2, 17, InnerWidth , InnerHeight

			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			
			Text width/2,8,msg,True,True
			
			Viewport 2, 17, InnerWidth ,InnerHeight
			
			;Draw Edit Content
			Local WCount% = 0
			Local LineCount% = 0
			Local CharCount% = 0
			Local tempString$ = ""
			;Local tempString2$ = ""
			Local StringLength% = Len(retString$)
			Local CurrentChar$ = ""
			Local LineLength% = 0

			While CharCount < StringLength

				Repeat
					CharCount = CharCount + 1
					Currentchar$ = Mid$(retString$, CharCount,1)	
					If Charcount = CaratPos+1 Then tempString$ = tempString$ + CaratSymbol$
					tempString$ = tempString$ + CurrentChar$
					charWidth = CharWidths(Asc(CurrentChar))
					WCount = WCount + charWidth
				Until (WCount > InnerWidth - 8) Or (CharCount = StringLength) Or (Asc(CurrentChar) = 13)

				If Right$(tempString,1) = Chr(13) Then 
						tempString$ = Left(TempString$,Len(TempString$)-1)
				EndIf

			
				myRGB = GetRGB(TextCol)
				Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
				If (CaratPos = StringLength) And (CaratPos = CharCount) Then tempString = tempString + CaratSymbol
				Text InnerX,InnerY + (LineCount * fntHeight),tempString$,False,False
				
				LineCount = LineCount + 1
			
				tempString$  = ""

				WCount = 0


			Wend
		
		SetBuffer OldBuffer
	
	DrawImage EditWin,x,y	
	
	Viewport 0,0,GraphicsWidth(), GraphicsHeight()
	
	If Not rtnSubmit Then
		If Button(x+(Width/2)-95,y+Height-20,80,"OK",False,False,KEY_INSERT,False,BorderCol,BGCol,TextCol) Then leave = True
		If Button(x+(Width/2)+5,y+Height-20,100,"Cancel",False,False,KEY_ESCAPE,False,BorderCol,BGCol,TextCol) Then
			retString = ""
			leave = True
		EndIf
	EndIf
	
	Flip

Until leave = True

	FlushKeys()
	FlushMouse()

	FreeImage EditWin

	Return retString$

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetRGB                            ;
; converts an int to R/G/B colour            ;
; returns a type of TRGB                     ;
; example Usage:                             ;
; myRGB.TRGB = New TRGB                      ;
; myRGB = GetRGB($FF55FF)                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function GetRGB.TRGB(InColour%)

Local tempRGB.TRGB = New TRGB
	tempRGB\ColRed = InColour% Shr 16 And 255 Shl 0
	tempRGB\ColGreen = InColour% Shr 8 And 255 Shl 0
	tempRGB\ColBlue = InColour% Shr 0 And 255 Shl 0
Return tempRGB

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION ListBox                       ;
; returns the index of the selected item ;
; parameters:                            ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function ListDlg%(X%, Y%, Width%, Height%, Items.TStringList,  BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)
;			myRGB = GetRGB(TextCol)
;			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

SetFont Font

;;;;;;
;VARS;
;;;;;;

	Local BorderWidth% = 2
	
	Local InnerX% = X + BorderWidth
	Local InnerY% = Y + BorderWidth

	Local InnerWidth% = Width - (BorderWidth * 2)
	Local InnerHeight% = Height - (BorderWidth * 2)

	Local ListWin = CreateImage(Width, Height)

	Local LastTipRect = CreateImage(1,FontHeight())

	Local Selected% = -1
	Local ScrollOffset% = 0
	Local ScrollBarWidth = 12
	Local leave = False
	Local Result = -1
;;;;;;
;MAIN;
;;;;;;

If GetCount(items) < 1 Then Return -1

While Not Leave

	;check keyboard input
	If KeyHit(1) Then 
		Result = -1
		Leave = True
	EndIf
	
	;28 Or 156 = Return Or Enter
	If KeyHit(28) Or KeyHit(156) Then
		Result=Selected
		Leave = True
	EndIf
	
	;up arrow
	If KeyHit(200) Then 
		selected = selected -1
		If selected < 0 Then selected = 0
	EndIf
	
	;down arrow
	If KeyHit(208) Then 
		selected = selected + 1
		If selected > GetCount(Items)-1 Then Selected = Getcount(Items)-1
	EndIf

	;check mouse input
	
	mx = MouseX()
	my = MouseY()

	If (mx > InnerX+2) And (mx < InnerX + (InnerWidth-ScrollWidth-4)) Then
		If (my > InnerY+2) And (my < (InnerY + (InnerHeight-2)) ) Then
			If MouseDown(1) Then			

				Selected = ( ( (my - InnerY) - ScrollOffset) / FontHeight())
				If Selected < 0 Then selected = 0
				If selected > GetCount(Items)-1 Then selected = Getcount(Items)-1

			EndIf
			
			;maybe do a tooltip here if the item the mouse 
			;is over is longer than the width of the list

		EndIf
	EndIf


	;draw listbox

	If GetCount(items) * FontHeight() > InnerHeight Then 
		ScrollBarWidth = 16
	Else 
		ScrollBarWidth = 0
	EndIf
	
	InnerWidth = ((Width - (BorderWidth * 2)) - ScrollBarWidth ) + 4

	oldbuffer = GraphicsBuffer()
	SetBuffer ImageBuffer(ListWin)

	;draw Border
	myRGB = GetRGB(BorderCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect 0, 0, Width, Height, True

	;Draw background
	myRGB = GetRGB(BGCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect BorderWidth, BorderWidth, InnerWidth - (BorderWidth*2), InnerHeight - (BorderWidth), True

	;clip to inner rectangle
	Viewport BorderWidth + 2, BorderWidth + 2, InnerWidth-8, InnerHeight-8
	
	;draw the text
	For i% = 0 To GetCount(items)-1
		If i = selected Then
		
			;draw a rect over the selected area
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed+2, myRGB\ColGreen+2, myRGB\ColBlue+2
			;for some reason, changing the following colour to black (0,0,0), draws as transparent

			;Color 10,10,10
			Rect BorderWidth + 2, (i * FontHeight())+ ScrollOffset, InnerWidth%, FontHeight(), True

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

		Else
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		EndIf

		Text BorderWidth+2, (i * FontHeight())+ ScrollOffset, Strings(items, i), False, False
	Next
	
	Viewport 0,0,Width,Height
	
	
	SetBuffer oldbuffer
	
		
	DrawImage Listwin, x,y


	mz = MouseZSpeed()

	If Button (X + Width - ScrollBarWidth, y + BorderWidth, 12, "­", False, True) Or mz = 1 Then
		;scroll up
		ScrollOffset = ScrollOffset + FontHeight()
		If ScrollOffset > 0 Then ScrollOffset = 0
	EndIf
	
	If Button (x + Width - ScrollBarWidth, (y + Height - FontHeight()) - BorderWidth, 12, "¯", False, True) Or mz = -1 Then
		;scroll down
		ScrollOffset = ScrollOffset - FontHeight()
		If ScrollOffset < -( (GetCount(Items)-1) * FontHeight()) Then ScrollOffset = -( (GetCount(Items)-1) * FontHeight())
	EndIf
			
			
			
			If selected > -1 Then s$ = Strings(items, selected)
			If StringWidth(s$)>InnerWidth-4 Then 
				tooltip(InnerX+2,InnerY + (Selected * FontHeight()),s$)
			EndIf

	Flip

	
Wend

Return result

End Function


;;;;;;;;;;;;;;;;;;;;
; FUNCTION ToolTip ;
;;;;;;;;;;;;;;;;;;;;

Function ToolTip(x,y,txt$)
	Color 255,255,225
	Rect x,y,StringWidth(txt$)+4,FontHeight()+4,True
	Color 0,0,0
	Rect x,y,StringWidth(txt$)+4,FontHeight()+4,False
	Text x+2,y+2,txt$
End Function



place the following in editor.bb just before the FLIP command:
	;test section
	;L Key for list
	;If KeyDown(38) Then DebugLog List(10,10,180,200,"test1|test2|test3",0)
	If KeyDown(38) Then 
		;lbShow = True
		
		mySL.TStringList = Create()
			addItem(mySL, "Item 1")
			addItem(mySL, "Item 2")
			addItem(mySL, "Item 3")
			addItem(mySL, "Item 4")
			addItem(mySL, "Item 5")
			addItem(mySL, "Item 6 is a longer item than the others, I am testing the overflow issue and it appears to clip nicely.")
			addItem(mySL, "Item 7")
			addItem(mySL, "Item 8")
			addItem(mySL, "Item 9")
			addItem(mySL, "Item 10")
			addItem(mySL, "Item 7")
			addItem(mySL, "Item 8")
			addItem(mySL, "Item 9")
			addItem(mySL, "Item 10")
			addItem(mySL, "Item 7")
			addItem(mySL, "Item 8")
			addItem(mySL, "Item 9")
			addItem(mySL, "Item 10")
			addItem(mySL, "Item 7")
			addItem(mySL, "Item 8")
			addItem(mySL, "Item 9")
			addItem(mySL, "Item 10")
			addItem(mySL, "Item 7")
			addItem(mySL, "Item 8")
			addItem(mySL, "Item 9")
			addItem(mySL, "Item 10")
		DebugLog ListDlg(10,10,240,350,mySL)
	EndIf
	
	;slowdown issues with this
	;If lbShow Then
		;DebugLog ListDlg(10,10,240,350,mySL)
	;EndIf
	
	If KeyDown(18) Then 
		InputBox$("Welcome to Intex Systems", 100, 100, 300, 300, False, "InputBox1", $004400, $00FF00, $002200)
		FlushMouse()
	EndIf


press L with debug on to see the ListBox functioning

There are some issues with it still, for instance the tooltip and the up and down arrows selecting the item does not scroll the box.

I also added colour options to the various controls, as demonstrated by pressing E whilst the editor is running.

*EDIT*
there is an issue with the OK and CANCEL buttons on the test inputbox in that when you press them, you end up overwriting the tile underneath. No amount of FlushMouse() commands or bashing the keyboard with a banana seems to affect it.

*EDIT*
oh yeah, nice graphics btw Rob :)

OK, new players.bb got it working I think... It's sometimes a bit flaky... need to look into it, but the basics are working.

It still needs the updated dirdif in utils.bb up there ^^^

players.bb

;==========================================================================================
;"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:
;	- 9/5/2004 POedBoy
;
;		Player_DrawAll() added instead of code floating in main loop 
;
;	- ?????? ?????? 
;
;
;	- 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 ownedWeapons.weapon[MAX_WEAPONS]
	Field name$
	Field x#
	Field y#
	Field speed#
	Field frame
	Field Clip
	Field ammo
	Field health#
	Field fpause,foot
	Field dir,credits
	Field id
	Field fireRate,tempFR
	Field weapon.weapon
	Field targetdir
	Field IsFiring,IsFiringTimer
	Field lives
	Field hurtCount ; this is used to play the hurt sound at a reasonable repeat rate
	Field score, kills, shots, doors
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/player2.png",64,64,0,128) : MaskImage playergfx,255,0,255
Global player_one_start_x,player_one_start_y
Global player_two_start_x,player_two_start_y

Dim player_footfall(1)
	player_footfall(0)=LoadSound("sfx/step.wav")
	player_footfall(1)=LoadSound("sfx/step2.wav")

 
;==========================================================================================
;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\health = 100
	pl\fpause = 0
	pl\dir = 0
	pl\id = id
	;Ammo stuff
	pl\Clip = 2
	pl\ammo = 15
	pl\lives = 5
	pl\speed = 2

	CheckVis(Floor(pl\x/32),Floor(pl\y/32))	
	
	Player(id)=pl
	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

	firing = False

	; get input
	If control(pright,pl\id) And pl\x<7552 Then mr=True
	If control(pleft,pl\id) And pl\x>0 Then ml=True
	If control(pup,pl\id) And pl\y>0 Then mu=True
	If control(pdown,pl\id) And pl\y<7552 Then md=True
		
	; weapons (player specific)
	If control(p_weapon1,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponBroadhurst))
	If control(p_weapon2,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponDalton))
	If control(p_weapon3,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponRobinson))
	If control(p_weapon4,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponRyxx))
	If control(p_weapon5,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponStyrling))
	If control(p_weapon6,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponImpact))
	
	If control(pAction,pl\id) Then runActionScript(pl) ; action key
				
	If control(pfire1,pl\id)
		fireWeapon(pl,pl\dir*22.5)
		firing = True
	EndIf
	
	; restrict players to the visible screen
	If pl\x-GOffsetX > GraphicsWidth()-32 And mr=True Then mr=False
	If pl\x-GOffsetX < 32 And ml=True Then ml=False
	If pl\y-GOffsety > GraphicsHeight()-32 And md=True Then md=False
	If pl\y-GOffsety < 32 And mu=True Then mu=False
		
	; Object Collision (walls, doors etc)
	
	If mr=True And ml=True Then ml=False
	If mu=True And md=True Then md=False
	
	If mr Then direct=direct + "R"
	If mu Then direct=direct + "U"
	If ml Then direct=direct + "L"
	If md Then direct=direct + "D"
	
	targetdir=-1
	
	If direct = "U" Then targetdir=0
	If direct = "RU" Then targetdir =2
	If direct = "R" Then targetdir =4 
	If direct = "RD" Then targetdir = 6
	If direct = "D" Then targetdir = 8
	If direct = "LD" Then targetdir = 10
	If direct = "L" Then targetdir = 12
	If direct = "UL" Then targetdir = 14	
	
	newx = pl\x + (Sin(targetdir*22.5)*playerradius)
	newy = pl\y - (Cos(targetdir*22.5)*playerradius)
	
	If gettile(newx,newy,0)=0 And (mu Or mr Or md Or ml) Then move=True
	
	tile=map(newx/32,newy/32,LayerObject)
	
	If tile>0
		If Instr(objectdef(tile)\trigger,ScriptTrigger_OnTouch)
			RunScript(pl,objectdef(tile),ScriptTrigger_OnTouch,newx,newy)
		EndIf
	EndIf

	; If you're Not firing change the direction you're looking
	If Not firing
		If targetdir>-1 Then pl\targetdir=targetdir
		If turndelay = 0
			pl\dir = dirdif (pl\dir,pl\targetdir)
		EndIf
	EndIf

	ScreenX = ScreenX + pl\x
	ScreenY = ScreenY + pl\y
	Player_Count = Player_Count+1
	
	; collect objects
	If map(pl\x/32,pl\y/32,LayerObject)>0 
		If Instr(objectdef(map(pl\x/32,pl\y/32,LayerObject))\trigger,ScriptTrigger_OnOver) Then RunScript(pl,objectdef(map(pl\x/32,pl\y/32,LayerObject)),ScriptTrigger_OnOver,pl\x,pl\y)
	End If

	;Animation
	If move = True
		pl\x = pl\x + (Sin(targetdir*22.5) * pl\speed)
		pl\y = pl\y - (Cos(targetdir*22.5) * pl\speed)
		pl\fpause = (pl\fpause + 1) Mod 10
		If pl\fpause = 0 Then pl\frame = (pl\frame+1) Mod 8
	EndIf
		
	; MOVED: This is in player_affectHealth below.
	;If pl\health = 0 Then
		;TODO: Death of player
	;End If	

Next

End Function


Function Player_GiveHealth(p.player, h#)
	p\health = p\health + h
	If p\health > 100 Then
		p\health = 100
			
	End If

End Function

Function Player_DrawAll()
	Local pl.Player
	For pl.player = Each player
		DrawImage playergfx,pl\x-32-ScreenX,pl\y-32-ScreenY,pl\frame+(pl\dir*8);+(Pl\IsFiring*120)
	Next
End Function

Function keycheck(player,keyid%)
	For p.pickedup = Each pickedup
		If p\player = player And p\obj =keyid Then Delete p:Return True
	Next
	Return False
End Function

Function Player_affectHealth(p.player,h#)
	p\health = p\health - h
	
	; this sound is repeated too quickly.
	; I've added a hurtcount field to the player to slow it down
	If p\hurtcount=0
		SoundPitch(hurt_sound,44000+Rand(-3000,3000))
		playoneshot(hurt_sound,p\x,p\y)
		p\hurtcount=100	; 100 is good, 10 is very fast, 200 is slow
	EndIf
	p\hurtcount=p\hurtcount-1
	
	If p\health =< 0 Then
		; rebirth
		p\health = 100
		p\lives=p\lives-1
		; play spinny animation here
		If p\lives=0
			; replaced with end of game bit
			Cls
			Print "End of game"
			WaitKey
			End
		EndIf		
	EndIf	
End Function

; moved here for editor compat.
Function ShowMap(i)
	; this is a very naff map, mainly intended for helping to test the vis functions
	p.player=Player(i)
	x=p\x/2:y=p\y/2
	;TODO: Initial position is dodgy, should be centred on the player...
	
	Repeat
		Cls
		drawmap(x,y,1,2)
		; don't make it too easy, leave out the objects... ;-)
		;TODO: trouble is, we need the doors...
		drawmap(x,y,3,2)
		drawmap(x,y,4,2)
		;TODO: need to show players location!
		
		If control(pup,i) Then y=y-8
		If control(pdown,i) Then y=y+8
		If control(pleft,i) Then x=x-8
		If control(pright,i) Then x=x+8
		
		Flip
	Until KeyHit(1)
	
	FlushKeys	
End Function
;additional player specific functions can be added here later as needed..

; temporarily moved from map.bb (editor will call for script functions)
Function DamageTile(x,y,val)
	;if the tile is not damageable then leave this function

	If x < 0 Then Return
	If y < 0 Then Return
	If x > 7552 Then Return
	If y > 7552 Then Return	

	x = Floor(x/32)
	y = Floor(y/32)

	If map(x,y,LayerHits) <0 Then Return

	map(x,y,LayerHits) = map(x,y,LayerHits) - val
	
	;if run out of hits
	If map(x,y,LayerHits) <1 Then 
		
		If map(x,y,LayerObject)>0 Then 
			If Instr(objectdef(map(x,y,LayerObject))\trigger,ScriptTrigger_OnDestroy) Then 
				;TODO: we probably need to keep track of which player owns which bullet, and pass that player in here
				RunScript(Player(1),objectdef(map(x,y,LayerObject)),ScriptTrigger_OnDestroy,x*32,y*32)
			Else
				;default action for any other destructible object
				Map(x,y,LayerObject) = 0 
				Map(x,y,LayerCollision) = 0
			End If			
		End If
		
	EndIf		
End Function


New aliens.bb

Const STANDARD_ALIEN 		= 0
Const FACE_HUGGER_ALIEN		= 1

;==========================================================================================
;TYPES
;==========================================================================================
Type alien
	Field x
	Field y
	Field frame
	Field health#
	Field fpause
	Field dir
	Field id
	Field sdelay
	Field targetdir
	Field mode$,image
	Field frameTotal
	Field visible ; are they currently visible to the player?
	Field speed#
	
	Field radius
	Field offset
	Field kind	
End Type

Global aliengfx = LoadAnimImage("gfx/alien2.png",64,64,0,128) : MaskImage aliengfx,255,0,255
Global facehugger_gfx = LoadAnimImage("gfx/hugger2.png",32,32,0,128) : MaskImage facehugger_gfx,255,0,255




Function SpawnAlien(X%,Y%,id,kind=STANDARD_ALIEN)
	al.alien = New alien
	
	al\x = X
	al\y = Y
	al\frame = 0
	al\health = 10
	al\fpause = 3
	al\dir = 0
	al\id = id
	al\sdelay = 0
	al\mode="newroam"
	al\speed = 1
	al\visible=gettile(al\x,al\y,LAYER_VISIBLE)
	
	al\kind = kind
	Select kind
		Case 0: ; standard alien
			al\radius=20
			al\offset=32
			al\frameTotal = 8
			al\image=aliengfx
		Case 1: ; face hugger
			al\radius=10
			al\offset=16
			al\frameTotal = 8
			al\image=facehugger_gfx
	End Select		
End Function

Function Alien_Die(al.alien)
	
	If al\kind = 0 Then createparticle(al\x,al\y,0,0,1000,0,7,alienblood,32,0)
	If al\kind = 1 Then createparticle(al\x,al\y,0,0,500,3,7,alienblood,32,0)
	playoneshot(snd_aliendeath,al\x,al\y)
	
	;create death splat
	n=Rand(20)+5
	For i=1 To n
		d=Rand(359)
		f=Rand(0,3)
		createparticle(al\x,al\y,Sin(d)*2,Cos(d)*2,Rand(10,100),f,f,particles,16)	
	Next
	
	Delete al.alien
			
End Function

Function alien_hit(al.alien,damage#=1.0)
	
	al\health = al\health - damage
	al\mode="underattack"
	
	If Rand(0,2)=0 Then playoneshot(snd_alienhit(Rand(0,3)),al\x,al\y)
	
	
	
	;random alien blood splats
	d=Rand(0,359)
	f=Rand(0,3)
	createparticle(al\x,al\y,Sin(d)*2,Cos(d)*2,Rand(10,100),f,f,particles,16)
		
	If al\health<=0 Then 
		alien_die(al)
		;Return true so we know the alien died
		Return True
		
	End If
	
	Return False
	
End Function


Function Alien_DrawAll()
	Local al.alien
	For al.alien = Each alien
		If al\visible Then 
			DrawImage al\image,al\x-al\offset-screenx,al\y-al\offset-screeny,(al\dir * al\frameTotal) +al\frame
		End If
	Next
End Function

Function DEBUG_drawAlienState()
	Local al.alien
	For al.alien = Each alien
		If al\visible Then 
			bText al\x-screenx,al\y-screeny,al\mode,True,True
		End If
	Next
End Function



Function update_aliens()

acount=0
	
For al.alien = Each alien

	oldmode$ = al\mode

	If al\visible

		acount=acount+1
	
	
		move=False
		direct$=""
		mr=False
		ml=False
		mu=False
		md=False
		
		; basic alien follow AI
		
		dis = 1000
		targetx=0
		targety=0
		For pl.player = Each player
			ndis = Sqr(((al\x-pl\x)*(al\x-pl\x))+((al\y-pl\y)*(al\y-pl\y)))
			If ndis<dis
				targetx=pl\x
				targety=pl\y
				dis=ndis
			EndIf
		Next
		
		
		If dis>500 And al\mode="underattack" Then al\mode="attack"
		
		; if a player is in range then attack
		If dis<1000
		
		
			If al\mode<>"underattack"
			
			
				; can alien see a player?
				
				For dd=-90 To 90 Step 30
				x=al\x
				y=al\y
				xd=Sin(al\dir*22.5+dd)*64
				yd=-Cos(al\dir*22.5+dd)*64
	
				
				ld=10
				cansee=False
				Repeat
					
					x=x+xd
					y=y+yd
					
					For pl.player = Each player
						If circlesoverlap(x,y,al\radius*4,pl\x,pl\y,playerradius) Then cansee=True:ld=1
					Next
					If x<0 Or x>7552 Or y<0 Or y>7552 Then x=0:y=0:id=1
					If gettile(x,y,0)=1 Then cansee=False:ld=1			
				
					ld=ld-1
				Until ld=0
				
				If cansee = True Then Exit
				
				Next
				
				If cansee And al\mode="roam" Then al\mode="attack"
				If cansee=False And al\mode="attack" Then al\mode="roam"
			EndIf
			
			
			;If al\mode="underattack" Then al\mode="attack"
					
			If al\mode="attack" Or al\mode="underattack"
				If al\x<targetx Then mr=True
				If al\x>targetx Then ml=True
				If al\y<targety Then md=True
				If al\y>targety Then mu=True
			EndIf
			
			If al\mode="roam"
				t=al\dir
				If t>12 Or t<4 Then mu=True
				If t>8 Then ml=True
				If t>4 And t<12 Then md=True
				If t<8 Then mr=True
			EndIf
					
			If al\mode="newroam"
				t=Rand(0,15)
				If t>12 Or t<4 Then mu=True
				If t>8 Then ml=True
				If t>4 And t<12 Then md=True
				If t<8 Then mr=True
				al\mode="roam"
			EndIf
			
	
		EndIf
		
		; check collisions with other aliens
		For al1.alien = Each alien
			If al\id<>al1\id
			
				If mr And circlesoverlap(al\x+2,al\y,al\radius,al1\x,al1\y,al1\radius) Then mr=False
				If ml And circlesoverlap(al\x-2,al\y,al\radius,al1\x,al1\y,al1\radius) Then ml=False
				If md And circlesoverlap(al\x,al\y+2,al\radius,al1\x,al1\y,al1\radius) Then md=False
				If mu And circlesoverlap(al\x,al\y-2,al\radius,al1\x,al1\y,al1\radius) Then mu=False
				
			EndIf
	
		Next
		
		; check collisions with players	
		For pl.player = Each player
		        If mr And circlesoverlap(al\x+2,al\y,al\radius,pl\x,pl\y,playerradius) Then mr=False
		        If ml And circlesoverlap(al\x-2,al\y,al\radius,pl\x,pl\y,playerradius) Then ml=False
			If md And circlesoverlap(al\x,al\y+2,al\radius,pl\x,pl\y,playerradius) Then md=False
			If mu And circlesoverlap(al\x,al\y-2,al\radius,pl\x,pl\y,playerradius) Then mu=False
					
			;Check for player damage
			If circlesoverlap(al\x,al\y,al\radius*1.2,pl\x,pl\y,playerradius) Then
				
				Player_affectHealth(pl,playerHealthDecrease)
				

					
			End If
		
		Next
		
		
		
	
		; Don't hit walls
		If mr Then
			If gettile(al\x+al\radius,al\y,0)=0 Then 
				If al\sDelay=0 Then al\x=al\x+1
				move=True
				direct=direct+"R"
			End If
				
			
		End If
		If ml Then 
			If gettile(al\x-al\radius,al\y,0)=0 Then 
				If al\sDelay=0 Then al\x=al\x-1
				move=True
				direct=direct+"L"
			End If
	
		End If
		If mu Then
			If gettile(al\x,al\y-al\radius,0)=0 Then 
				If al\sDelay=0 Then al\y=al\y-1
				move=True
				direct=direct+"U"
			End If
		End If
		If md Then 
			If gettile(al\x,al\y+al\radius,0)=0 Then 
				If al\sDelay=0 Then al\y=al\y+1
				move=True
				direct=direct+"D"
			End If	
		End If
		
		If move=False And al\mode="roam" Then al\mode="newroam"
		
		al\sdelay = (al\sdelay+1) Mod 2
		
		
		; animation frame control
		If move
			al\fpause = (al\fpause+1) Mod 5
			If al\fpause = 0 Then 
				al\frame = (al\frame+1) Mod al\frameTotal
			End If	
		EndIf
	
		If direct = "U" Then al\targetdir=0
		If direct = "RU" Then al\targetdir =2
		If direct = "R" Then al\targetdir =4 
		If direct = "RD" Then al\targetdir = 6
		If direct = "D" Then al\targetdir = 8
		If direct = "LD" Then al\targetdir = 10
		If direct = "L" Then al\targetdir = 12
		If direct = "LU" Then al\targetdir = 14
		
		If turndelay = 0
			al\dir = dirdif (al\dir,al\targetdir)
	
		EndIf

	EndIf
	
	If al\mode<>oldmode And (al\mode="attack" Or al\mode="underattack")
		playoneshot(snd_alienattack,al\x,al\y)
	EndIf

	If al\visible=0 Then
		If gettile(al\x,al\y,LAYER_VISIBLE)>0 Then al\visible=1
	End If
		
Next ; next alien

End Function


New GFX as required for this stuff.

http://www.mentalillusion.co.uk/tmp/gfx.zip


I'll be updating aliens.bb again at some point to allow aliens to have different speeds too. And revamp the AI somewhat.

The collisions on the player.bb needs updating now as you don't slide along walls, I'll sort this too, just need a bit of time. This needs to be sorted so I can use the same code for the aliens.

Perty you can get the new version from my site: www.3030deathwar.co.uk/downloads/ab/code.zip & www.3030deathwar.co.uk/downloads/ab/media.zip

I fixed your problem with the tile underneath being changed. I just added a 250ms delay after you get the input. That always works! I think we might need some more tiles. Can anyone do these? Things like transparent boxes at different angles, more walls, more floors, more everything to add some variation. We could also do with an alien-type theme tileset for when you get into the hive. Anyone feel upto adding to coffeebean's great tile graphics?

New in this version:
03-10-04 :
Rob
- New media! - new Alien and player images. Revamp of walking code.
- New alien.bb and player.bb. fixed player movement.
- Fixed wall sliding.
- New Media! - Female player image
Perturbatio
- Editor: Added dialogue box with new input. 
- Editor: Added stringlists
Snader
- Variation on the intex graphics (used, old saved as object(old).png)
Rims
- Editor: Rooms(v2) added again! See "editor-room.bb" for notes. Shortcut=R
- Editor: A new map will load a default.obj to use...
- Editor: Added new load room functions using perty's stringlists.
- Editor: Added a simple undo for tiles as well as entire room placement.


Player 3:

This is a female model I did ages ago... may as well make use of it!



Players.bb

Fixed sliding collision bug

;==========================================================================================
;"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:
;	- 9/5/2004 POedBoy
;
;		Player_DrawAll() added instead of code floating in main loop 
;
;	- ?????? ?????? 
;
;
;	- 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 ownedWeapons.weapon[MAX_WEAPONS]
	Field name$
	Field x#
	Field y#
	Field speed#
	Field frame
	Field Clip
	Field ammo
	Field health#
	Field fpause,foot
	Field dir,credits
	Field id
	Field fireRate,tempFR
	Field weapon.weapon
	Field targetdir
	Field IsFiring,IsFiringTimer
	Field lives
	Field hurtCount ; this is used to play the hurt sound at a reasonable repeat rate
	Field score, kills, shots, doors
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/player3.png",64,64,0,128) : MaskImage playergfx,255,0,255
Global player_one_start_x,player_one_start_y
Global player_two_start_x,player_two_start_y

Dim player_footfall(1)
	player_footfall(0)=LoadSound("sfx/step.wav")
	player_footfall(1)=LoadSound("sfx/step2.wav")

 
;==========================================================================================
;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\health = 100
	pl\fpause = 0
	pl\dir = 0
	pl\id = id
	;Ammo stuff
	pl\Clip = 2
	pl\ammo = 15
	pl\lives = 5
	pl\speed = 2

	CheckVis(Floor(pl\x/32),Floor(pl\y/32))	
	
	Player(id)=pl
	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

	firing = False

	; get input
	If control(pright,pl\id) And pl\x<7552 Then mr=True
	If control(pleft,pl\id) And pl\x>0 Then ml=True
	If control(pup,pl\id) And pl\y>0 Then mu=True
	If control(pdown,pl\id) And pl\y<7552 Then md=True
		
	; weapons (player specific)
	If control(p_weapon1,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponBroadhurst))
	If control(p_weapon2,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponDalton))
	If control(p_weapon3,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponRobinson))
	If control(p_weapon4,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponRyxx))
	If control(p_weapon5,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponStyrling))
	If control(p_weapon6,pl\id) Then EquipWeapon(pl\id,getWeaponFromName(weaponImpact))
	
	If control(pAction,pl\id) Then runActionScript(pl) ; action key
				
	If control(pfire1,pl\id)
		fireWeapon(pl,pl\dir*22.5)
		firing = True
	EndIf
	
	; restrict players to the visible screen
	If pl\x-GOffsetX > GraphicsWidth()-32 And mr=True Then mr=False
	If pl\x-GOffsetX < 32 And ml=True Then ml=False
	If pl\y-GOffsety > GraphicsHeight()-32 And md=True Then md=False
	If pl\y-GOffsety < 32 And mu=True Then mu=False
		
	; Object Collision (walls, doors etc)
	
	If mr=True And ml=True Then ml=False
	If mu=True And md=True Then md=False
	
	If mr Then direct=direct + "R"
	If mu Then direct=direct + "U"
	If ml Then direct=direct + "L"
	If md Then direct=direct + "D"
	
	targetdir=-1
	
	If direct = "U" Then targetdir=0
	If direct = "RU" Then targetdir =2
	If direct = "R" Then targetdir =4 
	If direct = "RD" Then targetdir = 6
	If direct = "D" Then targetdir = 8
	If direct = "LD" Then targetdir = 10
	If direct = "L" Then targetdir = 12
	If direct = "UL" Then targetdir = 14	
	
	newx = pl\x + (Sin(targetdir*22.5)*playerradius)
	newy = pl\y - (Cos(targetdir*22.5)*playerradius)
	
	xspeed# = (Sin(targetdir*22.5) * pl\speed)
	yspeed# = - (Cos(targetdir*22.5) * pl\speed)
		
	If mu Or mr Or md Or ml Then move=True
	
	If gettile(newx,pl\y,0) > 0 Then xspeed = 0
	If gettile(pl\x,newy,0) > 0 Then yspeed = 0
	
	tile=map(newx/32,newy/32,LayerObject)
	
	If tile>0
		If Instr(objectdef(tile)\trigger,ScriptTrigger_OnTouch)
			RunScript(pl,objectdef(tile),ScriptTrigger_OnTouch,newx,newy)
		EndIf
	EndIf

	; If you're Not firing change the direction you're looking
	If Not firing
		If targetdir>-1 Then pl\targetdir=targetdir
		If turndelay = 0
			pl\dir = dirdif (pl\dir,pl\targetdir)
		EndIf
	EndIf

	ScreenX = ScreenX + pl\x
	ScreenY = ScreenY + pl\y
	Player_Count = Player_Count+1
	
	; collect objects
	If map(pl\x/32,pl\y/32,LayerObject)>0 
		If Instr(objectdef(map(pl\x/32,pl\y/32,LayerObject))\trigger,ScriptTrigger_OnOver) Then RunScript(pl,objectdef(map(pl\x/32,pl\y/32,LayerObject)),ScriptTrigger_OnOver,pl\x,pl\y)
	End If

	;Animation
	If move = True
		pl\x = pl\x + xspeed
		pl\y = pl\y + yspeed
		pl\fpause = (pl\fpause + 1) Mod 10
		If pl\fpause = 0 Then pl\frame = (pl\frame+1) Mod 8
	EndIf
		
	; MOVED: This is in player_affectHealth below.
	;If pl\health = 0 Then
		;TODO: Death of player
	;End If	

Next

End Function


Function Player_GiveHealth(p.player, h#)
	p\health = p\health + h
	If p\health > 100 Then
		p\health = 100
			
	End If

End Function

Function Player_DrawAll()
	Local pl.Player
	For pl.player = Each player
		DrawImage playergfx,pl\x-32-ScreenX,pl\y-32-ScreenY,pl\frame+(pl\dir*8);+(Pl\IsFiring*120)
	Next
End Function

Function keycheck(player,keyid%)
	For p.pickedup = Each pickedup
		If p\player = player And p\obj =keyid Then Delete p:Return True
	Next
	Return False
End Function

Function Player_affectHealth(p.player,h#)
	p\health = p\health - h
	
	; this sound is repeated too quickly.
	; I've added a hurtcount field to the player to slow it down
	If p\hurtcount=0
		SoundPitch(hurt_sound,44000+Rand(-3000,3000))
		playoneshot(hurt_sound,p\x,p\y)
		p\hurtcount=100	; 100 is good, 10 is very fast, 200 is slow
	EndIf
	p\hurtcount=p\hurtcount-1
	
	If p\health =< 0 Then
		; rebirth
		p\health = 100
		p\lives=p\lives-1
		; play spinny animation here
		If p\lives=0
			; replaced with end of game bit
			Cls
			Print "End of game"
			WaitKey
			End
		EndIf		
	EndIf	
End Function

; moved here for editor compat.
Function ShowMap(i)
	; this is a very naff map, mainly intended for helping to test the vis functions
	p.player=Player(i)
	x=p\x/2:y=p\y/2
	;TODO: Initial position is dodgy, should be centred on the player...
	
	Repeat
		Cls
		drawmap(x,y,1,2)
		; don't make it too easy, leave out the objects... ;-)
		;TODO: trouble is, we need the doors...
		drawmap(x,y,3,2)
		drawmap(x,y,4,2)
		;TODO: need to show players location!
		
		If control(pup,i) Then y=y-8
		If control(pdown,i) Then y=y+8
		If control(pleft,i) Then x=x-8
		If control(pright,i) Then x=x+8
		
		Flip
	Until KeyHit(1)
	
	FlushKeys	
End Function
;additional player specific functions can be added here later as needed..

; temporarily moved from map.bb (editor will call for script functions)
Function DamageTile(x,y,val)
	;if the tile is not damageable then leave this function

	If x < 0 Then Return
	If y < 0 Then Return
	If x > 7552 Then Return
	If y > 7552 Then Return	

	x = Floor(x/32)
	y = Floor(y/32)

	If map(x,y,LayerHits) <0 Then Return

	map(x,y,LayerHits) = map(x,y,LayerHits) - val
	
	;if run out of hits
	If map(x,y,LayerHits) <1 Then 
		
		If map(x,y,LayerObject)>0 Then 
			If Instr(objectdef(map(x,y,LayerObject))\trigger,ScriptTrigger_OnDestroy) Then 
				;TODO: we probably need to keep track of which player owns which bullet, and pass that player in here
				RunScript(Player(1),objectdef(map(x,y,LayerObject)),ScriptTrigger_OnDestroy,x*32,y*32)
			Else
				;default action for any other destructible object
				Map(x,y,LayerObject) = 0 
				Map(x,y,LayerCollision) = 0
			End If			
		End If
		
	EndIf		
End Function


Ok, rob, I've added your stuff. The latest version can be found at the links above. Hopefully Perty'll put em on his site soon.

Just done a new face hugger... and it's discusting! Took ages to animate it but it was worth it!

Once I get the new alien.bb written where we can have different speeds of alien too, that hugger will skuttle around very quickly... scary!



I'm noticing collision issues with objects, sometimes I have to walk over a key or other object several times before it will pick up, and if it's near a wall it becomes very awkward.
also, the key at the beginning of the test map seems to give five keys and doesn't disappear.

Another couple of things:
if the player walks along the top following a face hugger, they cannot shoot them with anything other than the flame-thrower because.

If the player walks to the far right of the map, they are prevented from going within about 6 squares of the edge.

Pert, yeah, I noticed that too, I'm looking into the sorting the collisions. Not sure why it's any different, but it is for some reason. The five keys thing, no idea about that?!

edit..

fixed it... it's a float thing! Just put this bit over the top of the collect object in players.bb

	; collect objects
	
	xx=Floor(pl\x/32)
	yy=Floor(pl\y/32)
	
	If map(xx,yy,LayerObject)>0 
		If Instr(objectdef(map(xx,yy,LayerObject))\trigger,ScriptTrigger_OnOver) Then RunScript(pl,objectdef(map(xx,yy,LayerObject)),ScriptTrigger_OnOver,pl\x,pl\y)
	End If



There's still a bug in aliens.bb as the aliens are overlapping... I'm not too worried about that though as I'm going to be re-writing that soon.

made various modifications to gui.bb:
;Global font = LoadFont("Arial.ttf",15)
;Global symbFont = LoadFont("Symbol.ttf",15)

Include "inc\stringlist.bb"
Dim CharWidths(1)

Const KeyRepeat% = 100
Const CaratSymbol$ = "¦"

Type TRGB
	Field ColRed%
	Field ColGreen%
	Field ColBlue%
End Type


Global myRGB.TRGB = New TRGB

Type TCarat
	;X and Y in characters not pixels
	Field X%
	Field Y%
	Field PX%
	Field PY%
	Field Symbol$ = "¦"
End Type

Type TKeyState
	Field Scancode%
	Field Ascii%
	Field Shift
	Field Ctrl
End Type


Type TLine
	Field LineNum%
	Field Txt$
	Field Owner$
End Type


;;;;;;;;;;;;;;;;;;;;
; FUNCTION InitGUI ;
;;;;;;;;;;;;;;;;;;;;
Function InitGUI()

	SetFont font

;INPUT BOX SETUP
;Get the character widths
Dim charwidths(512)
	charwidths(32) = 4
	For c = 33 To 512
		charwidths(c) = StringWidth(Chr$(c))
	Next
End Function


;;;;;;;;;;;;;;;;;;;
; FUNCTION Button ;
;;;;;;;;;;;;;;;;;;;

Function Button(x,y,width,name$,active=False, symbol=False, ShortCutKey=KEY_NONE, ShowShortCut = True, OffCol%=$A0A0A0,  OverCol%=$C8C8C8, TextCol%=$000000)
;VARS
	Local result = False
	
;MAIN
	
	If RectsOverlap(MouseX(),MouseY(),1,1,x,y,width,16) Then 
		myRGB = GetRGB(OverCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
	Else 
		myRGB = GetRGB(OffCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
	EndIf
	Rect x,y,width,16

	myRGB = GetRGB(TextCol)
	Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue


	If Symbol Then SetFont symbFont

	If (ShortCutKey > KEY_NONE) And (ShowShortCut) Then name = name + " ("+ KeyNames(ShortCutKey) +")"

	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 result = True

	If ShortCutKey > KEY_NONE Then
		If KeyDown(ShortCutKey) Then Result = True
	EndIf

	Return Result
	
End Function 



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION InputBox									 ;
; Parameters:                                        ;
; msg$ : any message to display above the input box  ;
; x,y : top left coords                              ;
; width, height: outer width and height of inputbox  ;
; rtnSubmit : if the return key is pressed, then     ;
;             automatically submit the text			 ;
;             If this is false, then an OK button is ;
;             displayed at the bottom of the box     ;
; DefaultText : automatically inserts this into the  ;
; input box, the carat will be positioned at the end ;
; of this text.                                      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function InputBox$(Msg$,x,y,width,height,rtnSubmit=True, DefaultText$="", BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)

	SetFont Font

;;;;;;
;vars;
;;;;;;

	Local leave = False
	Local InnerWidth = Width - 6
	Local InnerHeight = Height - 40
	Local InnerX = 6
	Local InnerY = 20
	Local retString$ = ""
	Local fntWidth = FontWidth()/4
	Local fntHeight = FontHeight()
	Local EditWin = CreateImage(width, height)
	Local BGImage = CreateImage(GraphicsWidth(), GraphicsHeight())
	Local Delimiters$ = "|() "+Chr$(13)
	Local FoundDelim = False
	Local TopLine = 0
	
	Local Carat.TCarat = New TCarat
			Carat\X = 0
			Carat\Y = 0

	Local SelStart% = 0 
	Local SelEnd% = 0
	Local CaratPos% = 0
	
	Local ScrollPos = 0
	
	Local ScrollWidth = 12

;;;;;;
;main;
;;;;;;

CopyRect 0,0,GraphicsWidth()-1, GraphicsHeight()-1, 0,0, GraphicsBuffer(), ImageBuffer(BGImage)

If rtnSubmit Then InnerHeight = Height - 6
FlushKeys()
CaratPos = Len(DefaultText)
retString = retString+DefaultText

Repeat
	;quit the function without returning any text if escape is pressed
	If KeyHit(1) Then 
		leave = True
		retString$ = ""
	EndIf
	
	;;;;;;;;;;;;;;;;;;;;;
	;get character input;
	;;;;;;;;;;;;;;;;;;;;;
	get = GetKey()
	
	
	
	If Get = 13 Then
		If rtnSubmit Then 
			leave = True ;if return is pressed and rtnSubmit is True then leave
		Else
			LeftSide$ = Left$(retString$,CaratPos)
			RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
			retString$ = LeftSide$ + Chr(get) + RightSide$
			CaratPos = CaratPos + 1
		EndIf
	ElseIf KeyDown(14); backspace
		If MilliSecs()-LastInput > KeyRepeat Then
			If Len(retString$) > 0 Then 
				LeftSide$ = Left$(retString$,CaratPos)
				RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
				retString$ = Left$(LeftSide$, Len(LeftSide$) -1) + RightSide$
			EndIf
			LastInput = MilliSecs()
			CaratPos = CaratPos - 1
			If CaratPos < 0 Then CaratPos = 0
		EndIf
	ElseIf KeyDown(203) ;Left Cursor
		If MilliSecs()-LastInput > KeyRepeat Then
		
			If KeyDown(157) ; CTRL ; Allow CTRL+Left to jump the carat pos to the next delimiter to the left of the cursor
				For i = CaratPos To 1 Step -1
					
					d = 1
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )	
						
						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i-1
							FoundDelim = True
						EndIf
						d = d + 1
					
					Wend
				
					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
				
				FoundDelim = False
			
			Else
				CaratPos = CaratPos - 1
				If CaratPos < 0 Then CaratPos = 0
			EndIf
			LastInput = MilliSecs()
		EndIf
	ElseIf KeyDown(205) ; RIGHT CURSOR
		If MilliSecs()-LastInput > KeyRepeat Then
			If KeyDown(157) ;CTRL ; Allow CTRL+RIGHT to jump the carat pos to the next delimiter to the right of the cursor

				For i = CaratPos+1 To Len(retString$)
					d = 1					
					While (d < Len(Delimiters$)+1) And (Not FoundDelim )

						If Mid(retString$, i,1) = Mid(Delimiters$, d,1) Then 
							CaratPos = i
							FoundDelim = True
						EndIf
						d = d + 1
					Wend				

					If FoundDelim Then Exit
				Next
				
				If Not FoundDelim Then CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
				
				FoundDelim = False
		
			Else
				CaratPos = CaratPos + 1
				If CaratPos > Len(retString$) Then CaratPos = Len(retString$)
			EndIf
			LastInput = MilliSecs()
		EndIf

	ElseIf KeyDown(207) ; end
		CaratPos = Len(retString$)
	ElseIf KeyDown(199) ; home
		CaratPos = 0
	ElseIf (get > 31) ;is a letter, number or symbol

		LeftSide$ = Left$(retString$,CaratPos)
		RightSide$ = Right$(retString$, Len(RetString)-CaratPos)
		retString$ = LeftSide$ + Chr(get) + RightSide$
		CaratPos = CaratPos + 1
		
	EndIf

		
		;Draw the edit window
		oldbuffer = GraphicsBuffer()
		SetBuffer ImageBuffer(EditWin)
			
			myRGB = GetRGB(BorderCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 0,0,width,height

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			Rect 2, 17, InnerWidth , InnerHeight

			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			
			Text width/2,8,msg,True,True
			
			Viewport 2, 17, InnerWidth ,InnerHeight
			
			;Draw Edit Content
			Local WCount% = 0
			Local LineCount% = 0
			Local CharCount% = 0
			Local tempString$ = ""
			;Local tempString2$ = ""
			Local StringLength% = Len(retString$)
			Local CurrentChar$ = ""
			Local LineLength% = 0

			While CharCount < StringLength

				Repeat
					CharCount = CharCount + 1
					Currentchar$ = Mid$(retString$, CharCount,1)	
					If Charcount = CaratPos+1 Then tempString$ = tempString$ + CaratSymbol$
					tempString$ = tempString$ + CurrentChar$
					charWidth = CharWidths(Asc(CurrentChar))
					WCount = WCount + charWidth
				Until (WCount > InnerWidth - 8) Or (CharCount = StringLength) Or (Asc(CurrentChar) = 13)

				If Right$(tempString,1) = Chr(13) Then 
						tempString$ = Left(TempString$,Len(TempString$)-1)
				EndIf

			
				myRGB = GetRGB(TextCol)
				Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
				If (CaratPos = StringLength) And (CaratPos = CharCount) Then tempString = tempString + CaratSymbol
				Text InnerX,InnerY + (LineCount * fntHeight),tempString$,False,False
				
				LineCount = LineCount + 1
			
				tempString$  = ""

				WCount = 0


			Wend
		
		SetBuffer OldBuffer
	
	DrawBlock BGImage,0,0
	DrawBlock EditWin,x,y	
	
	Viewport 0,0,GraphicsWidth(), GraphicsHeight()
	
	If Not rtnSubmit Then
		If Button(x+(Width/2)-95,y+Height-20,80,"OK",False,False,KEY_INSERT,False,BorderCol,BGCol,TextCol) Then leave = True
		If Button(x+(Width/2)+5,y+Height-20,100,"Cancel",False,False,KEY_ESCAPE,False,BorderCol,BGCol,TextCol) Then
			retString = ""
			leave = True
		EndIf
	EndIf
	
	DrawImage cursor,MouseX()-1,MouseY()-1
	
	Flip

Until leave = True

	FlushKeys()
	FlushMouse()

	

	FreeImage EditWin
	FreeImage BGImage

	Return retString$

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetRGB                            ;
; converts an int to R/G/B colour            ;
; returns a type of TRGB                     ;
; example Usage:                             ;
; myRGB.TRGB = New TRGB                      ;
; myRGB = GetRGB($FF55FF)                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function GetRGB.TRGB(InColour%)

Local tempRGB.TRGB = New TRGB
	tempRGB\ColRed = InColour% Shr 16 And 255 Shl 0
	tempRGB\ColGreen = InColour% Shr 8 And 255 Shl 0
	tempRGB\ColBlue = InColour% Shr 0 And 255 Shl 0
Return tempRGB

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION ListBox                       ;
; returns the index of the selected item ;
; parameters:                            ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function ListDlg%(X%, Y%, Width%, Height%, Items.TStringList,  BGCol%=$FFFFFF, TextCol%=$000000, BorderCol%=$A0A0A0)
;			myRGB = GetRGB(TextCol)
;			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

SetFont Font

;;;;;;
;VARS;
;;;;;;

	Local BorderWidth% = 2
	
	Local InnerX% = X + BorderWidth
	Local InnerY% = Y + BorderWidth

	Local InnerWidth% = Width - (BorderWidth * 2)
	Local InnerHeight% = Height - (BorderWidth * 2)

	Local ListWin = CreateImage(Width, Height)
	Local BGImage = CreateImage(GraphicsWidth(), GraphicsHeight())

	Local Selected% = -1
	Local ScrollOffset% = 0
	Local ScrollBarWidth = 12
	Local leave = False
	Local Result = -1
	Local FirstMouseHit = 0
	Local SecondMouseHit = 0
;;;;;;
;MAIN;
;;;;;;

CopyRect 0,0,GraphicsWidth()-1, GraphicsHeight()-1, 0,0, GraphicsBuffer(), ImageBuffer(BGImage)

If SL_GetCount(items) < 1 Then Return -1

While Not Leave

	;check keyboard input
	If KeyHit(1) Then 
		Result = -1
		Leave = True
	EndIf
	
	;28 Or 156 = Return Or Enter
	If KeyHit(28) Or KeyHit(156) Then
		Result=Selected
		Leave = True
	EndIf
	
	;up arrow
	If KeyHit(200) Then 
		selected = selected -1
		If selected < 0 Then selected = 0
	EndIf
	
	;down arrow
	If KeyHit(208) Then 
		selected = selected + 1
		If selected > SL_GetCount(Items)-1 Then Selected = SL_Getcount(Items)-1
	EndIf
	

	;check mouse input
	
	mx = MouseX()
	my = MouseY()

	If (mx > InnerX+2) And (mx < InnerX + (InnerWidth-ScrollWidth-4)) Then
		If (my > InnerY+2) And (my < (InnerY + (InnerHeight-2)) ) Then
			If MouseDown(1) Then			

				Selected = ( ( (my - InnerY) - ScrollOffset) / FontHeight())
				If Selected < 0 Then selected = 0
				If selected > SL_GetCount(Items)-1 Then selected = SL_Getcount(Items)-1

			EndIf
			
			;maybe do a tooltip here if the item the mouse 
			;is over is longer than the width of the list

		EndIf
	EndIf


	;draw listbox

	If SL_GetCount(items) * FontHeight() > InnerHeight Then 
		ScrollBarWidth = 16
	Else 
		ScrollBarWidth = 0
	EndIf
	
	InnerWidth = ((Width - (BorderWidth * 2)) - ScrollBarWidth ) + 4

	oldbuffer = GraphicsBuffer()
	SetBuffer ImageBuffer(ListWin)

	;draw Border
	myRGB = GetRGB(BorderCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect 0, 0, Width, Height, True

	;Draw background
	myRGB = GetRGB(BGCol)
		Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		Rect BorderWidth, BorderWidth, InnerWidth - (BorderWidth*2), InnerHeight - (BorderWidth), True

	;clip to inner rectangle
	Viewport BorderWidth + 2, BorderWidth + 2, InnerWidth-8, InnerHeight-8
	
	;draw the text
	For i% = 0 To SL_GetCount(items)-1
		If i = selected Then
		
			;draw a rect over the selected area
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
			;for some reason, changing the following colour to black (0,0,0), draws as transparent

			;Color 10,10,10
			Rect BorderWidth + 2, (i * FontHeight())+ ScrollOffset, InnerWidth%, FontHeight(), True

			myRGB = GetRGB(BGCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue

		Else
			myRGB = GetRGB(TextCol)
			Color myRGB\ColRed, myRGB\ColGreen, myRGB\ColBlue
		EndIf

		Text BorderWidth+2, (i * FontHeight())+ ScrollOffset, SL_Strings(items, i), False, False
	Next
	
	Viewport 0,0,Width,Height
	
	
	SetBuffer oldbuffer
	
	DrawBlock BGImage,0,0
		
	DrawBlock Listwin, x,y


	mz = MouseZSpeed()

	If Button (X + Width - ScrollBarWidth, y + BorderWidth, 12, "­", False, True) Or mz = 1 Then
		;scroll up
		ScrollOffset = ScrollOffset + FontHeight()
		If ScrollOffset > 0 Then ScrollOffset = 0
	EndIf
	
	If Button (x + Width - ScrollBarWidth, (y + Height - FontHeight()) - BorderWidth, 12, "¯", False, True) Or mz = -1 Then
		;scroll down
		ScrollOffset = ScrollOffset - FontHeight()
		If ScrollOffset < -( (SL_GetCount(Items)-1) * FontHeight()) Then ScrollOffset = -( (SL_GetCount(Items)-1) * FontHeight())
	EndIf


	If selected > -1 Then s$ = SL_Strings(items, selected)
	If StringWidth(s$)>InnerWidth-4 Then 
		tooltip(InnerX+2,InnerY + (Selected * FontHeight())+ScrollOffset,s$)
	EndIf

	DrawImage cursor,MouseX()-1,MouseY()-1

	Flip

Wend

FreeImage ListWin
FreeImage BGImage

Return result

End Function


;;;;;;;;;;;;;;;;;;;;
; FUNCTION ToolTip ;
;;;;;;;;;;;;;;;;;;;;

Function ToolTip(x,y,txt$)
	Color 255,255,225
	Rect x,y,StringWidth(txt$)+4,FontHeight()+4,True
	Color 0,0,0
	Rect x,y,StringWidth(txt$)+4,FontHeight()+4,False
	Text x+2,y+2,txt$
End Function


Fixed issue with using controls in fullscreen (mouse cursor disappearing).
Tooltips now appear over the correct item in the listbox no matter what the scrolloffset is.
All areas that are drawn on are redrawn correctly.

changed stringlist.bb:
; Use a reasonably large number to limit the number 
; of lines that a stringlist can contain
Const MaxStringListSize = 512

Type TStringItem
	Field FString$
	Field FObject%
	Field FUsed = False
End Type

Type TStringList
	Field FItems.TStringItem[MaxStringListSize]
	Field FCount
End Type


;CONSTRUCTOR;
;;;;;;;;;;;;;;;;;;;
; FUNCTION Create ;
;;;;;;;;;;;;;;;;;;;
Function SL_Create.TStringList()
	Local sList.TStringList = New TStringList
	;can add any initialization code here so that all new stringlists
	;start with the same values
	For t = 0 To MaxStringListSize
		sList\FItems.TStringItem[t] = New TStringItem
	Next
	Return sList
End Function



;DESTRUCTOR;
;;;;;;;;;;;;;;;;;;;;
; FUNCTION Destroy ;
;;;;;;;;;;;;;;;;;;;;
Function SL_Destroy(sList.TStringList)
	For t = 0 To MaxStringListSize
		Delete sList\FItems[t]
	Next
	Delete sList
End Function



;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetText ;
;;;;;;;;;;;;;;;;;;;;
;returns all the items as one single string
Function SL_GetText$(sList.TStringList)
;VARS
	Local result$ = ""
	
;MAIN
	For i = 0 To SL_GetCount(sList)
		result$ = result$ + sList\FItems[i]\FString$
	Next

	Return result$
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION Strings                                     ;
; return the string of the item at the specified index ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function SL_Strings$(sList.TStringList, Index%)
	Return sList\FItems[Index]\FString$
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION AddItem                                          ;
; if index > -1 then insert the item at the specified index ;
; will return the index the item is added at.               ;
; if the return value is <0 then an error has occured       ;
; (probably exceeded MaxStringListSize)                     ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function SL_AddItem(sList.TStringList, txt$, Obj%=0, Index%=-1)
	Local result = -1 ;set the default result to a failure, only a success will change this
	Local Count = SL_GetCount(sList)
	
	If Index >  MaxStringListSize Then Return -1
	If Count => MaxStringListSize Then Return -1
	
	If Index < 0 Then ;add to the end
		sList\FItems[Count]\FString$ = txt$
		sList\FItems[Count]\FObject% = Obj%
		sList\FItems[Count]\FUsed    = True
		result = Count
	Else
		For i = Count To Index + 1 Step -1
			sList\FItems[i]\FString$ = sList\FItems[i-1]\FString$
			sList\FItems[i]\FObject% = sList\FItems[i-1]\FObject%
			sList\FItems[i]\FUsed    = sList\FItems[i-1]\FUsed
		Next
		
		sList\FItems[Index]\FString$ = txt$
		sList\FItems[Index]\FObject% = Obj%
		sList\FItems[Index]\FUsed    = True

		result = Index
	EndIf

SL_GetCount(sList)

Return result

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION DeleteItem                      ;
; Delete the line with the specified index ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function SL_DeleteItem(sList.TStringList, Index%)
	;If the index passed is out of bounds then leave the function
	If (index < 0) Or (Index > MaxStringListSize) Then Return

	If Index < MaxStringListSize Then
		For i = Index To MaxStringListSize-1
			If i < MaxStringListSize Then
				sList\FItems[i]\FString$ = sList\FItems[i+1]\FString$
				sList\FItems[i]\FObject% = sList\FItems[i+1]\FObject%
				sList\FItems[i]\FUsed = sList\FItems[i+1]\FUsed
			EndIf
			;clear the next line, this will result in the last line not being used

				sList\FItems[i+1]\FString$ = ""
				sList\FItems[i+1]\FObject% = 0
				sList\FItems[i+1]\FUsed    = False
			;EndIf
		Next
	Else ;if the Index is equal to the MaxStringListSize then just clear it
		sList\FItems[Index]\FString$ = ""
		sList\FItems[Index]\FObject% = 0
		sList\FItems[Index]\FUsed = False
	EndIf

SL_GetCount(sList)

End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION GetCount                   ;
; Returns the number of items         ;
; in the list (Not THE HIGHEST INDEX) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function SL_GetCount(sList.TStringList)
;VARS
	Local Used = 1
	Local Count = 0
;MAIN

	While (Used <> 0) And (Count < MaxStringListSize)
		Used = sList\FItems[Count]\FUsed	
		If used Then Count = Count + 1
	Wend
	
	sList\FCount = Count
	
	Return sList\FCount
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;TEST;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;sl.TStringList = SL_Create()
;
;Print SL_Getcount(sl)
;SL_AddItem(sl,"Third Line of Text" + Chr$(13))
;Print SL_Getcount(sl)
;SL_AddItem(sl,"Fourth Line of Text")
;Print SL_Getcount(sl)
;Print SL_GetText(sl)
;SL_DeleteItem(sl,0)
;Print SL_GetText(sl)
;Print SL_Getcount(sl)
;Print SL_strings(sl,2)
;Print SL_GetText(sl)

;SL_AddItem(sl,"New Line inserted at 1",0,1)


;Print Str(sl)
;For i = 0 To SL_GetCount(sl)-1
;	Print SL_Strings(sl,i)
;Next

;SL_Destroy sl

;Print Str(sl)

;WaitKey()
;End


modifications to editor.bb:
		mySL.TStringList = SL_Create()
			SL_addItem(mySL, "Item 1")
			SL_addItem(mySL, "Item 2")
			SL_addItem(mySL, "Item 3")
			SL_addItem(mySL, "Item 4")
			SL_addItem(mySL, "Item 5")
			SL_addItem(mySL, "Item 6 is a longer item than the others, I am testing the overflow issue and it appears to clip nicely.")
			SL_addItem(mySL, "Item 7")
			SL_addItem(mySL, "Item 8")
			SL_addItem(mySL, "Item 9")
			SL_addItem(mySL, "Item 10")
			SL_addItem(mySL, "Item 7")
			SL_addItem(mySL, "Item 8")
			SL_addItem(mySL, "Item 9")
			SL_addItem(mySL, "Item 10")
			SL_addItem(mySL, "Item 7")
			SL_addItem(mySL, "Item 8 is also a really long item, let's see if it does a tooltip for this as well.")
			SL_addItem(mySL, "Item 9")
			SL_addItem(mySL, "Item 10")
			SL_addItem(mySL, "Item 7")
			SL_addItem(mySL, "Item 8")
			SL_addItem(mySL, "Item 9")
			SL_addItem(mySL, "Item 10")
			SL_addItem(mySL, "Item 7")
			SL_addItem(mySL, "Item 8")
			SL_addItem(mySL, "Item 9")
			SL_addItem(mySL, "Item 10")


*EDIT*
also started on reorganizing the input code in editor.bb:
		;Right Mouse Button Layer Handler
		If MouseDown(2) Then
			Select ActiveLayer
			
				Case LayerBase
					map(xpos,ypos,activelayer) = 1
					
				Case LayerObject
					map(xpos,ypos,ActiveLayer) = 0
					
				Case LayerBlock
					map(xpos,ypos,ActiveLayer) = 0
					
				Case LayerCollision
					map(xpos,ypos,LayerCollision) = 0
					map(xpos,ypos,LayerHits) = 0
					
			End Select
		EndIf
		


I put this between the IF MOUSEHIT(2) statement of the hitpoint layer and the IF KEYDOWN(28) statement.
it *should* be a replacement for all the If MouseDown(2) statements related to the activelayer/

Attempting to upload new Zips now...
I think I might be logging on at the wrong time of day for this, I think my server is running through a backup at the moment.

*EDIT*
Zips updated.

changed load function in map.bb, added LoadObjectFile function:
; load the map in
Function Load(filename$)

	If FileType(FileName$+".map") = 1
		filein = ReadFile(FileName$+".map")
		For layer = 0 To NumLayers
			For x=0 To 255
				For y=0 To 255
					map(x,y,layer)= ReadInt(filein)
				Next
			Next
		Next
		CloseFile filein
	Else
		DebugLog "Filename does not exist: " + FileName$+".map"
	EndIf
	
	LoadObjectFile(FileName$)
		
End Function


;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FUNCTION LoadObjectFile ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function LoadObjectFile(FileName$)
	;load the object file
	For od.objdef=Each objdef
		Delete od
	Next
	
	If FileType(FileName$+".obj") = 1
		filein = ReadFile(FileName$+".obj")
		NumObjects=parse(ReadLine(filein),"=",1)		
		ReadLine(filein) ; blank space
		If NumObjects>0 Then
			Dim objectdef.objdef(NumObjects)
			For i=1 To NumObjects
				objectdef(i)=New objdef
				objectdef(i)\image=Trim(parse(ReadLine(filein),"=",1))				
				objectdef(i)\trigger=Trim(parse(ReadLine(filein),"=",1))			
				;add a separator to the start to make searching simpler
				If Left(objectdef(i)\trigger,1)<>"|" Then objectdef(i)\trigger="|"+objectdef(i)\trigger
				objectdef(i)\name=Trim(parse(ReadLine(filein),"=",1))			
				
				For n=1 To CountString(objectdef(i)\trigger,"|")
					objectdef(i)\script[n]=ReadLine(filein)
				Next
				ReadLine(filein); blank space
			Next
		End If
		DebugLog numObjects+" objects loaded from "+FileName+".obj"
		CloseFile filein
	Else
		DebugLog "Filename does not exist: " + FileName$+".obj"
	EndIf	
End Function


in editor-include.bb - function CreateRandomMap() add:
LoadObjectFile("maps\default") to the end of the function

This will set default.obj to any new map including the one that is created on startup.

Perty, I think that codebox above where you say " made various modifications to gui.bb: " is actually the editor.bb. Is that right or was it supposed to be gui.bb?

I've been thinking about map detail. The current tileset has some detail like scorched tiles, bits of rubble and stuff but they've got a set floor tile to be with.

If we add another layer (at the end of the map array) we can add transparent tiles to any base layer and vary the look of the level considerably.

What do you all think? I think it's probably the best way to go.

Rims, my one issue would be performance... Maybe we should have that but make it optional, likewise we should probably make the over-layers optional too. The reason I say this is transparant layers kill performance on lower end machines.

Thinking a bit more about it, it would be better if it wasn't optional, as then furniture (lockers, desks, plants etc) wouldn't be floor dependant. Maybe we should make it optional on the over-layers but not on the base layer stuff.

Perty, I think that codebox above where you say " made various modifications to gui.bb: " is actually the editor.bb. Is that right or was it supposed to be gui.bb?


And this kids, is why you shouldn't post code at 4 in the morning...

updated.

I didn't think about the speed issues (bad programmer, bad). So you're saying we should have the extra layer for plants, barrels and such but make the "top" layer optional to speed up slower machines?

I'll get on with some changes then if this is the case. Ok perty. By the way, what time are these posts timestamped with? Is it US? NZ? They certainly aren't UK.

That sounds about right, also the good thing with this means you'd be able to destroy furniture/barrels etc without destorying the underlying base data, also it means once something been destoryed it can be replaced with a broken version.


Ok perty. By the way, what time are these posts timestamped with? Is it US? NZ? They certainly aren't UK.



They're stamped with Forum time. I originally did GMT but figured that since this is a multi-national project (at least potentially), I would use a common time zone.

And this kids, is why you shouldn't post code at 4 in the morning...
This is why I stop posting at midnight! You look back at post midnight posts and they're just gibberish!

sometimes your pre-midnight ones are just as bad, you bap sausage.

[edit: With regards to the new detail layer: I've jiggled the map array around so it's drawn in the right order. The detail layer is in and works pretty well. I've updated the tiles image but got bored half way though the words. I'm not even sure we need to do those.

Perty, could you pop this tiles.png image into the media.zip and obviously overwrite the old one.

New code.zip here with this being new:

05-10-04 :
Perturbatio
- Editor: Fixes and clearing up (gui.bb,stringlist.bb+editor.bb)
Rims
- Added new detail layer. Old maps will require slight reworking.
- Updated tiles.png with transparencies in appropriate places.
- Added "use_overlay_layer" global to optionally draw LayerTop



have people thought a little more on the sourceforge idea? If we were to use SF then any team member can upload files without having to wait for someone else (i.e. me) to do it (and without having to wait for my flaky ftp server to warm up).

I'm all for it. Did Mark set one up? Weren't we waiting on Rob's word or something? Could I ASK anymore questions? I'm all for the idea. Where is Mark, these days? What do you think Rob? It'll be a lot easier for us all. We could still use this forum 'n'all.

I've just checked it out and it costs $39 from what I can see, am I looking at the right place?

- Editor: Added new load room functions using perty's stringlists.


Rims, did you remove this? or am I just blind.
I was interested to see how you had implemented it.

*EDIT*

I'm sure the $39 is for the premium service, the basic one is free.

*EDIT* take a look here:
http://sourceforge.net/docman/display_doc.php?docid=14027&group_id=1#cost

Hi, been rather busy - away from home most of last week, and the week before that I had a very hectic week at work. Also my 1 year old daughter's been a bit poorly the past few days resulting in *very* sleepless nights. Like about a total of an hour last night. It's nothing serious though, and she seems better today (famous last words...)

As for SourceForge, I thought it was free for the basic service, which seemed adequate for what we need. We need all individuals who have contirbuted code (and who therefore own copyright on their code) to give their okay for us to use the GNU General Public License (discussed in the last post). I believe the only one not to do so explicitly is Rob...

Also, not sure who wants to submit it - I'm happy to, but it's kind of Rob's brainchild, so he may wish to do so...

*yawn* I think I'm gonna get some kip. At 7:30pm Tsk!

OK, I've registered and submitted a request to sourceforge with all the details of the project... just got to wait now for it to be approved.

We need all individuals who have contirbuted code (and who therefore own copyright on their code) to give their okay for us to use the GNU General Public License (discussed in the last post). I believe the only one not to do so explicitly is Rob...
Sorry, I didn't realise I needed to give the nod... Of course!

We will of course have to distribute the GNU GPL with the source from now on.

Perty, if you have a look at the room controls on the right the Load button opens the a stringlist with all the available rooms to load. Saving a new one will refresh the list. I was thinking about implementing a double click but got it wrong, so left it.

I just downloaded everything and I get index array out of bounds on start up... something's broken!

Also, a few gfx can be removed now I think...

hugger.png
intex-background.png
alien16.png

Rob, it could be due to the new Layer.

[edit
This is the most up to date version. It's my working version.

www.3030deathwar.co.uk/downloads/ab/code.zip
www.3030deathwar.co.uk/downloads/ab/media.zip

This version will *definitely* work. it's up.

The editor needs a manual of sorts... I've not fired it up for ages and I have no idea how to use it! How do you get the vis collisions in? What is the green collision box? What's the hitpoint layer?

I love the room drawing thing, very cool.


In engine.bb the object layer needs to be drawn before the players and aliens. I think the order should be:
	drawmap(ScreenX,ScreenY,1)
	drawparticles(0)
	drawmap(ScreenX,ScreenY,2)
	drawmap(ScreenX,ScreenY,3)
	drawbullets()
	Alien_DrawAll()
	Player_DrawAll()
	drawAnimations()
	drawparticles(1)
	drawmap(ScreenX,ScreenY,4)
	drawHUD()


Also set the turn delay to: turndelay = (turndelay + 1) Mod 3 as there's twice as many turns now it looks a little sluggish.

Also when you shoot out doors sometimes the door doesn't open and it just removes a single door block, the vis doesn't fire and it just looks weird!

And your new test.map doesn't have enough keys to get round without blasting out a few doors. (I was going to fix this but I couldn't work out how to use the editor!)

If you change the hugger2 to hugger3 prepared to be grossed out!

The new detail layer works really well, I like it a lot, it certainly gives the level more life, you were spot on with that suggestion.

For bandwidth issues it could be worth splitting the sound out of the media too, and put dates on when each of the files were updated, this way if only the code is updated or only the graphics then people won't be downloading all the sound and graphics and everything each time. Also helps with our 56k friends.

Additional ToDo:
Assign different players to their graphics, I think certain guns should only be able to be carried by certain players. Ie Player3.png should move a little faster than player2.png but not be able to carry the really heavy weapons for example. Anyway, that's a 'discuss' issue.

Oh, one more thing, the overview map I think is way too detailed, I think all it needs to show are collision blocks and doors and bugger all else, it could be a pixel line drawing, after all, it's a plan not a photograph. Again... discuss!

Anyway, that's about it for now... Time for bed said Zeberdee!

I think that the overview map should only show a certain distance around you, it should in fact be a solid object detector (i.e. radar).

Also, I think we should implement a motion detector, just cos' it'd be cool.

The motion detector is cool, however, not sure how useful it would be as you can already see aliens coming around the corner. And if you knew there were aliens behind doors it would take a bit of the suspense away.

I think the map should just be a line drawing of the bits you've been to, don't include the non vizzed stuff.

Another thought...

The room creator I think could be 25 blocks, this way you can have 2 layers of stuff around the edges this will mean you can add the shadow blocks in too.

It's bloody good as it stands though.

Really really simple map thing... Totally unoptimised in that is used plot! (gasp!) but this is the sort of thing I think the map should be.

Function ShowMap(i)
	Cls
	Color 255,255,255
	For x=0 To 255
	For y=0 To 255
	If map(x,y,LayerCollision)>0 Then Color 0,0,0 Else Color 100,100,100
	If map(x,y,layer_visible)=0 Then Color 100,0,0
	Plot x,y
	Next
	Next
		
	Flip
		
	Repeat:Until KeyHit(1)
	
	FlushKeys	
End Function


I'll be away from sort of thursday evening until sunday so someone else will need to host updates for a while (or someone could sign up for Sourceforge).

I wold host it, but I don't know how to put the code together and stuff.

>> or someone could sign up for Sourceforge

I have done... you have to wait a couple of days to be approved.

I'll host it again pert, it's a new month so I've got fresh bandwidth limits again. Can you continue to host music.zip and media.zip as that's not updating much? It'll just take the strain of my limited bandwidth.

Does this show too much? I made it twice as big and show doors and the players.

Function ShowMap(i)
	Cls
	Color 255,255,255
	For x=0 To 255
	For y=0 To 255
	If map(x,y,LayerCollision)>0
		If map(x,y,LayerCollision)=czVisDynamic 
			; dynamic
			Color 0,100,0
		Else
			; static
			Color 0,0,0 
		EndIf		
	Else 
		Color 100,100,100
	EndIf
	If map(x,y,layer_visible)=0 Then Color 100,0,0
	Rect x*2,y*2,2,2
	Next
	Next
		
	For p.player=Each player
		If p = First player Then Color 255,0,0 Else Color 0,0,255
		Rect Floor(p\x/32)*2,Floor(p\y/32)*2,2,2
	Next	
		
	Flip
		
	Repeat:Until KeyHit(1)
	
	FlushKeys	
End Function


That looks cool to me rims, It'll probably be better to do it with a imagebuffer and writepixelfasts too for performance (theres a couple of writergb function in intexnew.bb). Of course with the bigger map you're going to have to sort out some kind of y offset as you're printing 512 pixels tall on a 480 screen.

I was going to make mine double size, include doors and players too. I also thought it would be nice to make the players glow.

Function ShowMap(i)

	For n=1 To 2
	Cls
	Color 255,255,255
	For x=0 To 255
	For y=0 To 255
	If map(x,y,LayerCollision)>0
		If map(x,y,LayerCollision)=czVisDynamic 
			; dynamic
			Color 0,100,0
		Else
		 	; static
		 	Color 0,0,0 
	 	EndIf		 
 	Else 
 		Color 100,100,100
 	EndIf
 	If map(x,y,layer_visible)=0 Then Color 100,0,0
 	Rect x*2,y*2,2,2
 	Next
 	Next
	Flip
	Next

	
	c=255
	Repeat	
 	For p.player=Each player
		If p = First player Then Color c,0,0 Else Color 0,0,c
		Rect Floor(p\x/32)*2,Floor(p\y/32)*2,2,2
		c=c-1
		If c=150 Then c=255
	Next	
		
	Flip
		
	Until KeyHit(1)
	
	FlushKeys	
End Function


To fix the VIS not working on blown up doors, replace the players.bb->damageTile function with this one:
Function DamageTile(x,y,val)
	;if the tile is not damageable then leave this function

	If x < 0 Then Return
	If y < 0 Then Return
	If x > 7552 Then Return
	If y > 7552 Then Return	

	x = Floor(x/32)
	y = Floor(y/32)

	If map(x,y,LayerHits) <0 Then Return

	map(x,y,LayerHits) = map(x,y,LayerHits) - val
	
	;if run out of hits
	If map(x,y,LayerHits) <1 Then 
		
		If map(x,y,LayerObject)>0 Then 
			If Instr(objectdef(map(x,y,LayerObject))\trigger,ScriptTrigger_OnDestroy) Then 
				;TODO: we probably need to keep track of which player owns which bullet, and pass that player in here
				RunScript(Player(1),objectdef(map(x,y,LayerObject)),ScriptTrigger_OnDestroy,x*32,y*32)				
			Else
				;default action for any other destructible object
				Map(x,y,LayerObject) = 0 
				Map(x,y,LayerCollision) = 0
			End If			
			CheckVis(x,y)
		EndIf		
	EndIf		
End Function

Also, why is the map getting drawn twice? I've removed the for i=1 to 2 at the top of the drawMap functions.

It's drawn twice, once for each buffer, seeing as you're flipping for the glowing players you need to same image on each buffer or it goes flicka-flicka-flicka-flika...

[edit] You're not talking about my bit of code? Don't know about that other bit you're talking about.

The vis seems to work correctly on yellow doors but no other colours. Also when you blow up non yellow doors you only blow out one block of the door. I'm guessing it's because the yellow doors are the original and were coding, the new doors were missed!

It's drawn twice, once for each buffer, seeing as you're flipping for the glowing players you need to same image on each buffer or it goes flicka-flicka-flicka-flika...

DOH! I hardly ever run fullscreen and in windowed you don't get that flicker.

With regards to the vis, the above function replacement for damageTile should work. It adds a "checkVis(x,y)" call after you've blown the door so even if the door has a single tile missing the new vis gets updated. As for the other parts of the door getting blown up, it's because the default action for killing a door *without* a script attached is just to kill that tile and not any surrounding tiles. I'm not sure where the piece of code that accomplished this before has gone.

New code.zip

06-10-04 :
Rob
- Updated Player.bb with a new map (looks like the intex system now)
- Updated player.bb to deal with different characters with differect graphic sets and speeds
- Updated Engine.bb to get draw order correct.
Rims
- Updated Player.bb (damagetile function) to fix vis problem

Sorted the destorying doors problem, they needed an ondestroy script too.

test.obj
total objects = 37

image = 0
trigger = onover()
description = Ammo
addammo(50)|remove(me)

image = 1
trigger = onover()
description = Health
addhealth(10)|playsoundonce(health_pickup)|remove(me)

image = 2
trigger = onover()
description = Key (yellow)
addkey(1)|playsoundonce(key_pickup)|remove(me)

image = 3
trigger = onover()
description = Key (red)
addkey(2)|playsoundonce(key_pickup)|remove(me)

image = 4
trigger = onover()
description = Key (green)
addkey(3)|playsoundonce(key_pickup)|remove(me)

image = 5
trigger = onover()
description = Key (blue)
addkey(4)|playsoundonce(key_pickup)|remove(me)

image = 6
trigger = ontouch()|ondestroy()
description = Door (yellow)
checkkey(1)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 7
trigger = ontouch()|ondestroy()
description = Door (yellow)
checkkey(1)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 8
trigger = onover()
description = 100 Credit
addcredit(100)|remove(me)

image = 9
trigger = onover()
description = 50 Credit
addcredit(50)|remove(me)

image = 10
trigger = onover()
description = 10 Credit
addcredit(10)|remove(me)

image = 11
trigger = ontouch()|ondestroy()
description = Door (red)
checkkey(2)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 12
trigger = ontouch()|ondestroy()
description = Door (red)
checkkey(2)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 13
trigger = ontouch()|ondestroy()
description = Door (blue)
checkkey(4)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 14
trigger = ontouch()|ondestroy()
description = Door (blue)
checkkey(4)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 15
trigger = ontouch()|ondestroy()
description = Door (green)
checkkey(3)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 16
trigger = ontouch()|ondestroy()
description = Door (green)
checkkey(3)|opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 17
trigger = onaction()
description = Intex System
intex()

image = 18
trigger = onaction()
description = Intex System
intex()

image = 19
trigger = onaction()
description = Intex System
intex()

image = 20
trigger = onaction()
description = Intex System
intex()

image = 21
trigger = onover()
description = weapon (Broadhurst DJ Twinfire 3LG)
pickupweapon(1)|remove(me)

image = 22
trigger = onover()
description = weapon (Dalton Arc Flame)
pickupweapon(2)|remove(me)

image = 23
trigger = onover()
description = weapon (Robinson Plasma Gun)
pickupweapon(3)|remove(me)

image = 24
trigger = onover()
description = weapon (Ryxx Firebolt MK22)
pickupweapon(4)|remove(me)

image = 25
trigger = onover()
description = weapon (Styrling Multimatic)
pickupweapon(5)|remove(me)

image = 26
trigger = onover()
description = weapon (High Impact Astro Laser)
pickupweapon(6)|remove(me)

image = 27
trigger = onload()
description = alien spawn point (normal alien) [normal?]
createalien(alien)|remove(me)

image = 28
trigger = onload()
description = alien spawn point (hugger)
createalien(hugger)|remove(me)

image = 29
trigger = onevery(10)
description = every 10 seconds create an alien
createalien(alien)

image = 30
trigger = onevery(30)
description = every 30 seconds create an alien
createalien(alien)

image = 31
trigger = onevery(10)
description = every 10 seconds create a hugger
createalien(hugger)

image = 32
trigger = onevery(30)
description = every 30 seconds create a hugger
createalien(hugger)

image = 33
trigger = onload()
description = player one start position
positionplayer(1)|remove(me)

image = 34
trigger = onload()
description = player two start position
positionplayer(2)|remove(me)

image = 35
trigger = ontouch()|ondestroy()
description = no key door (horizontal)
opendoor()|remove(nearby)
opendoor()|remove(nearby)

image = 36
trigger = ontouch()|ondestroy()
description = no key door (vertical)
opendoor()|remove(nearby)
opendoor()|remove(nearby)



Explode function added to weapons.bb

Test it out by hitting E and an explosion will appear where the player is.

The explosion creates bullets so this could cause chain reactions when you blow up barrels and stuff.

Added an extra field to the bullet to know if it's a scenary bullet, this will also be used for autocannons kills do not get added to player counts.

New code.zip download here...

Well Done everyone. This is looking very nice indeed.

It's a shame you're not using quads in Blitz3D because then you'd be able to rotate for all the 8 directions and you'd cut down on your graphics by about 90% for each unit.

But then of course some low end machines may struggle.

Updated code zip again: New code.zip
Added a barrel object: New objects.png

Added barrel explode script and barrel object. Examples of the exploding barrels are if you come out from the red door and go up to the green door there are a bunch of barrels there, they explode and clear their collisions.

Am I the only person working on this now?

Enay, personally I'd like to see this use a full 3D engine then just have animated models for the graphics, then you wouldn't even need to worry about the rotations and you'd have proper dynamic lights etc etc, Still keep it top down though.

Well with a 2D quad engine you'd be able to zoom in and out which would make for some quite useful effects (zooming in and out when the players get close to each other like in Loaded/Reloaded) on the PSX and as I said before you'd easily with one line of code be able to make the screen rotate and keep the player facing the same direction.

Are you thinking full models like Metal Gear Solid style from top view?

I'd like to see this go to 3d as well. We could really benefit from a few sprites here and there. It'd be a major overhaul though and we're probably better off just getting this version done upto a standard before messing with the engine.
Am I the only person working on this now?

Yes.

Are you thinking full models like Metal Gear Solid style from top view?
Probably... but never played MGS. But basically a full 3D game, just have it play in 2D from above.
Yes.
Bugger!

I think Enay means to use a 2d Sprites in 3d mode approach such as Jims Spritemaster or something.

Keep up the good work guys this is looking awesome.

I've just created a new alien model, it animates better and looks better, also updated alien.bb to improve the animation, I'll upload it when people join in again as it's only a cosmetic improvement.

I was thinking we need to balance the weapons somewhat, also I was thinking it could be quite cool to have some fireproof bad guys for example who can't be killed with the flame thrower. Also other bad guys who are retardant to different attacks.

Anyway just a thought.

I'll upload it when people join in

I've not contributed anything to the project but I have been following your progress from day 1. It's been really interesting to see this progress, keep it up guys!

Just to say that I am still around, but seem to be rather busy at the moment. I'm still checking in regularly, and hope to start contributing again soon!

I've done new player 1 and player 2 graphics too now. Looking at reworking the alien.bb code so it's... well... better!


New Thread