Network FPS Code for you playing pleasure

Blitz3D Forums/Blitz3D Programming/Network FPS Code for you playing pleasure

srcoder(Posted 2007) [#1]
I recently stuck to gether this code as a challenge to make a network game in blitz3d that does not need any media.
It's here for your use to play with as you like. If you decide to sell it please send me some of the profit!
It's very simple, slightly buggy, peer to peer (so keep the users down) with procedurally generated texture, players and arena. Have fun!!

Mod Msg: bugous version removed.


_33(Posted 2007) [#2]
Function UpdatePlayer() is broken, missing an EndIf. But the code is clearly broken, as the other errors that pop up proves in the compiler.


srcoder(Posted 2007) [#3]
Very sorry my FPS loving friends, I posted an out of date version (untested and sloppy) Please enjoy this tested version No media required.

;Network stuff to create a player and initialize the game

Global delayamount = 5
Global delaycount = 0

netgame = StartNetGame()

If netgame = 0
	Print "Network game not stared"
	Print "exiting........"
	End
EndIf

Print "Netgame result = " + netgame

;create a player for this machine


Global playerName$ = Input$("What is your name?   ")
Global playerID = CreateNetPlayer(playerName$)

If playerID = 0 
	Print ("Player could not be created")
	StopNetGame()
	End
EndIf

Print "Player " + playerName$ + " has ID " + playerID
Print " Press a key to start"
WaitKey()


Global incoming$[100]

Global killedfont

killedfont = LoadFont("Arial",24)
SetFont killedfont
Color 250,250,250
Global killedmessage$ = " "





;///////////////////////////////////////////////////////////////////////////////////////////////////
Const TYPE_P4B = 6
Const TYPE_ENEMY = 5
Const TYPE_BULLET = 4
Const TYPE_SCENERY = 3
Const TYPE_PLAYER = 1


Graphics3D 640,480
SetBuffer BackBuffer()

timer = CreateTimer(60)
SeedRnd(MilliSecs())

light = CreateLight()
RotateEntity light,10,45,0

Global player = CreatePivot()
Global PlayerStatus = 1
EntityRadius player,2,4
EntityType player,TYPE_PLAYER
Global camera = CreateCamera(player)
CameraClsColor camera,0,0,100
Global campitch# = 0.0
x = Rnd(-4,4)
z = Rnd(-4,4)
PositionEntity player,(x*40)+10,0,(z*40)+10
PositionEntity camera,0,3,0
EntityType camera,TYPE_P4B
EntityRadius camera,3,5
MoveMouse 320,240
HidePointer


;create some textures for the arena
Global grasstex = CreateTexture(64,64)
SetBuffer TextureBuffer(grasstex)
For x = 0 To 64
	For y = 0 To 64
		Color 0,Rnd(100,255),0
		Plot x,y
	Next
Next
Global stonetex = CreateTexture(64,64)
SetBuffer TextureBuffer(stonetex)
For x = 0 To 64
	For y = 0 To 64
		c = Rnd(50,150)
		Color c,c,c
		Plot x,y
	Next
Next
;reset buffer to backbuffer
SetBuffer BackBuffer()


CreateArena()

Collisions TYPE_PLAYER,TYPE_SCENERY,2,2
Collisions TYPE_BULLET,TYPE_SCENERY,2,1
Collisions TYPE_BULLET,TYPE_P4B,1,1


While Not KeyDown(1)

UpdatePlayer()
UpdateEnemys()
UpdateBullets()
UpdateExplosions()
UpdateWorld()
RenderWorld()
PrintKilledMessage()
Flip()
WaitTimer(timer)
Wend

StopNetGame()

End


Function UpdatePlayer()

If playerstatus = 1

campitch# = campitch# + Float(MouseYSpeed())/5.0
If campitch# < -80 Then campitch = -80
If campitch# > 80 Then campitch = 80
TurnEntity player,0,Float(-MouseXSpeed())/5.0,0
RotateEntity camera,campitch,0,0
If KeyDown(17)
	MoveEntity player,0,0,0.5
EndIf
If KeyDown(31)
	MoveEntity player,0,0,-0.5
EndIf
If KeyDown(32)
	MoveEntity player,0.5,0,0
EndIf
If KeyDown(30)
	MoveEntity player,-0.5,0,0
EndIf

x# = EntityX(player)
If x# < -300 Then x# = -300
If x# > 300 Then x# = 300
z# = EntityZ(player)
If z# < -300 Then z# = -300
If z# > 300 Then z# = 300
PositionEntity player,x#,EntityY(player),z#

If MouseHit(1)
	b.bullet = CreateBullet(camera,PlayerID)
	SendBulletMessage(b)
EndIf
;now get message to send about our tank
;only do this every 10 frames or so

	If delaycount > delayamount
		SendPlayerMessage()
		delaycount = 0
	Else 
		delaycount = delaycount + 1
	EndIf

      ;check if a bullet has collided with the camera entity
      c = CountCollisions(camera)
        If c > 0
            ;get the handle of the bullet that has collided
            bullethandle = EntityCollided(camera,TYPE_BULLET)
            ;now find out which bullet it is so we can work out who shot it!
            For b.bullet = Each bullet
                If b\entity = bullethandle And b\PlayerID <> playerID
                    SendExplodedMessage(b\playerID)
                    CreateBigExplosion(EntityX(player), EntityY(player), EntityZ(player))
                    killer$ = NetPlayerName$(b\PlayerID)
                    playerstatus = 0
                    killedmessage$ = killer$ + " just killed you!!"
                End If
		    Next
        EndIf
Else
    If KeyHit(57)
        x = Rnd(-4,4)
        z = Rnd(-4,4)
        PositionEntity player,(x*40)+10,0,(z*40)+10
        playerstatus = 1
		SendRestartMessage()
		killedmessage$ = " "
    End If
EndIf

MoveMouse 320,240
End Function

Function UpdateEnemys()

While RecvNetMsg()

;check for player already being on the list
newplayer = True
For this.enemy = Each enemy
	If NetMsgFrom() = this\ID
		newplayer = False
	EndIf
Next
If newplayer = True
	;this mesage was from a player not in the list
	;create a new player
	n.enemy = CreateEnemy()
	n\ID = NetMsgFrom()
	n\name$ = NetPlayerName(n\ID)
	n\status = 1
	HideEntity(n\entity)
EndIf

;now process this message
For e.enemy = Each enemy
	If NetMsgFrom() = e\ID
		msgtype = NetMsgType()
		Select msgtype
			Case 1
				;position message. 
				If e\status = 1
				DecodeIncoming(NetMsgData())
				PositionEntity(e\entity,incoming[1],0,incoming[2])
				ShowEntity(e\entity)
				EndIf
			Case 2
				;bomb message
				If e\status = 1
				DecodeIncoming(NetMsgData())
				CreateEnemyBullet(e,incoming[1],incoming[2],incoming[3])
				EndIf
			Case 3
				;player exploded message
				HideEntity(e\entity)
				CreateBigExplosion(EntityX(e\entity),EntityY(e\entity),EntityZ(e\entity))
				e\status = 0
			Case 4
				;player has restarted again
				ShowEntity(e\entity)
				e\status = 1
			Case 101
				;player has left the game
				FreeEntity e\entity
				Delete e			
		End Select
	EndIf
Next

Wend

End Function

Function PrintKilledMessage()
 Color 250,250,250
 Text 0,0,killedmessage$
End Function



Function CreateArena()
plane = CreatePlane()
ScaleTexture grasstex,10,10
EntityTexture plane,grasstex

For x = -100 To 100 Step 40
	For z = -100 To 100 Step 40
		c = CreateCube()
		ScaleEntity c,10,10,10
		PositionEntity c,x,9,z
		EntityTexture c, stonetex
		EntityType c,TYPE_SCENERY
	Next
Next
End Function

Type bullet
Field entity,PlayerID
Field xv#,yv#,zv#
Field age,lifespan
End Type

Function CreateBullet.bullet(entity,ID)
b.bullet = New bullet
b\entity = CreateSphere()
TFormVector 0,0,2,entity,0
b\xv# = TFormedX()
b\yv# = TFormedY()
b\zv# = TFormedZ()
PositionEntity b\entity,EntityX(entity,True),EntityY(entity,True),EntityZ(entity,True)
b\age = 0
b\lifespan = 100
b\PlayerID = ID
EntityType b\entity,TYPE_BULLET
EntityRadius(b\entity,1)
Return b
End Function

Function CreateEnemyBullet.bullet(e.enemy,xvel#,yvel#,zvel#)
b.bullet = New bullet
b\entity = CreateSphere()
b\xv# = xvel#
b\yv# = yvel#
b\zv# = zvel#
b\PlayerID = e\ID
PositionEntity b\entity,EntityX(e\entity,True),EntityY(e\entity,True)+3,EntityZ(e\entity,True)
EntityRadius b\entity,1.0
EntityType b\entity,TYPE_BULLET
b\age = 0
b\lifespan = 100
Return b
End Function


Function UpdateBullets()
For b.bullet = Each bullet
	b\age = b\age + 1
	TranslateEntity b\entity,b\xv#,b\yv#,b\zv#
	c = CountCollisions(b\entity)
	If b\age > b\lifespan Or c > 0 Or EntityY(b\entity) < 0.0
		CreateExplosion(EntityX(b\entity),EntityY(b\entity),EntityZ(b\entity))
		FreeEntity b\entity
		Delete b
	EndIf
Next
End Function

Type particle
Field entity,age,lifespan
Field xv#,yv#,zv#
End Type

Function CreateExplosion(x#,y#,z#)
For c = 1 To 20
	p.particle = New particle
	p\entity = CreateSphere()
	ScaleEntity p\entity,0.2,0.2,0.2
	PositionEntity p\entity,x#,y#,z#
	p\xv# = Rnd(-0.5,0.5)
	p\yv# = Rnd(0,0.5)
	p\zv# = Rnd(-0.5,0.5)
	p\age = 0
	p\lifespan = 60
Next
End Function

Function CreateBigExplosion(x#,y#,z#)
For c = 1 To 50
	p.particle = New particle
	p\entity = CreateSphere()
	ScaleEntity p\entity,1,1,1
	PositionEntity p\entity,x#,y#,z#
	p\xv# = Rnd(-0.5,0.5)
	p\yv# = Rnd(0,1)
	p\zv# = Rnd(-0.5,0.5)
	p\age = 0
	p\lifespan = 60
Next
End Function


Function UpdateExplosions()
For p.particle = Each particle
	TranslateEntity p\entity,p\xv#,p\yv#,p\zv#
	p\yv# = p\yv# - 0.05
	p\age = p\age + 1
	If p\age > p\lifespan
		FreeEntity p\entity
		Delete p
	EndIf
Next
End Function
	
Type enemy
Field name$,ID
Field entity
Field status
End Type

Function CreateEnemy.enemy()
e.enemy = New enemy
e\entity = CreateCone()
ScaleMesh e\entity,4,4,4
s = CreateSphere(8,e\entity)
PositionEntity s,0,4,0
EntityColor e\entity,100,0,0
EntityColor s,100,0,0
Return e
End Function

;network function////////////////////////////////////////////////////////////////////////////

Function DecodeIncoming(a$)
i = 1
x = 1
msg$ = ""
For x = 1 To Len(a$)
	char$ = Mid(a$,x,1)
	If char$ <> ","
		msg$ = msg$ + char$
	Else
		incoming[i] = msg$
		msg$ = ""
		i = i + 1
	EndIf
Next
incoming[i] = msg$
End Function




Function SendPlayerMessage()
;xposition,zposition,yrotation
msg$ = EntityX(player)+","+EntityZ(player)
	SendNetMsg(1,msg$,playerID,0)
End Function

Function SendBulletMessage(b.bullet)
;this passes the global velocities as well as the ID as messagetype 2
msg$ = b\xv#+","+b\yv#+","+b\zv#
	SendNetMsg(2,msg$,playerID,0)
End Function

Function SendExplodedMessage(killerID)
;just send a message of type 3
SendNetMsg(3,killerID,playerID,0)
End Function

Function SendRestartMessage()
;send a message of type 4
SendNetMsg(4,"r",playerID,0)
End Function



Damien Sturdy(Posted 2007) [#4]
Error: [codebox] and [codebox/] required.

The first line is hilighted when it happens.


stayne(Posted 2007) [#5]
I don't know much about network coding so I don't know how efficient this is... but regarldess thank you for posting it :).


srcoder(Posted 2007) [#6]
Yeah, just a cut and paste issue. Just put a ; there to comment it out.
It's not efficient due to the peer to peer method of message transfer. ie. each computer sends position/shoot/die/restart messages to every other computer. Thats a lot of messages. It works fine on my school network with up to 8 players but traffic gets a bit busy and jumpy with more.
What it does demonstrate is a simple way to use the built in StartNetGame() dialogue box which I have seen very little of in the forums.
It also has the added benefit of requiring NO MEDIA. so it's a single executable.
Use the code if you want.


jfk EO-11110(Posted 2007) [#7]
THanks for sharing. A working sample for StartNetGame() is surely very useful. Maybe it's not the first choice for a web based game. but for a lan network it may be perfect.
I'd suggest you post it also in the code archives.