James Bond the Dinosaur
Blitz3D Forums/Blitz3D Beginners Area/James Bond the Dinosaur
| ||
nevermind the title. I need some help making a first person shooter. I made my level, just a wall, floor and ceiling, and I know some Blitz3D programming, I just have NO idea how to put together an FPS. Thanks, O Reliable Blitz Forums. |
| ||
Really basic example: Not finished... Start with setting up 3D graphics Graphics3D 800, 600 SetBuffer BackBuffer() Set up your types Type bullettype Field entityhandle End Type Type badguytype Field entityhandle Field state End Type Load in your 3d objects light = CreateLight() player = CreatePivot() camera = CreateCamera(player) level = LoadMesh("level.b3d") weapon1 = LoadMesh("pistol.b3d", camera) bulletmesh = LoadMesh("bullet.b3d") badguymesh = LoadMesh("badguy.b3d") HideEntity bulletmesh HideEntity badguymesh etc... Create your beginning objects For iter = 1 to 10 badguy.badguytype = New badguytype badguy\entityhandle = CopyEntity(badguymesh) badguy\state = Rnd(1, 2) ;1=Guard 2=Search 3=Evade 4=Fire 5=Dead EntityType badguy\entityhandle, 3 EntityRadius badguy\entityhandle, .7, 2 Next Arrange your objects MoveEntity camera, 0, .8, 0 MoveEntity weapon1, .1, -.15, .1 MoveEntity player, 20, 1, -20 For bgiter.badguytype = Each badguytype PositionEntity iter\entityhandle, Rnd(100)-50, 1, Rnd(100)-50 Next etc... Set up collisions between all of the objects. EntityTypes and radiuses for badguys and bullets are set upon their creation. EntityType player, 1 EntityRadius player, .7, 2 EntityType level, 2 Collisions 1, 2, 2, 2 ;player to level Collisions 3, 2, 2, 2 ;badguy to level Collisions 4, 2, 2, 1 ;bullet to level Collisions 4, 3, 2, 1 ;bullet to badguy Then add a loop that updates the screen every frame. While Not Keyhit(1) ;insert additional code here UpdateWorld RenderWorld Flip Wend Inside of your loop (before UpdateWorld) add lines that handle how to move the player (camera) If Keydown(17) then MoveEntity player, 0, 0, .1 If Keydown(31) then MoveEntity player, 0, 0, -.1 If Keydown(30) then MoveEntity player, -.1, 0, 0 If Keydown(32) then MoveEntity player, .1, 0, 0 Next add lines that handle how to allow the player (camera) to look around TurnEntity player, 0, -MouseXSpeed()/5.0, 0 TurnEntity camera, MouseYSpeed()/5.0, 0, 0 If EntityPitch(camera) < -45 RotateEntity camera, -45, EntityYaw(camera), EntityRoll(camera) EndIf If EntityPitch(camera) > 45 RotateEntity camera, 45, EntityYaw(camera), EntityRoll(camera) EndIf MoveMouse GraphicsWidth()/2, GraphicsHeight()/2 Add code to allow the player to shoot If MouseHit(1) bullet.bullettype = New bullettype bullet\entityhandle = CopyEntity(bulletmesh) PositionEntity bullet\entityhandle, EntityX(weapon1, 1), EntityY(weapon1, 1), EntityZ(weapon1, 1) RotateEntity bullet\entityhandle, EntityPitch(weapon1, 1), EntityYaw(weapon1, 1), EntityRoll(weapon1, 1) EntityType bullet\entityhandle, 4 EntityRadius bullet\entityhandle, .01 EndIf Add code to move bullets every frame For biter.bullettype = Each bullettype MoveEntity biter\entityhandle, 0, 0, 2 If Abs(EntityX(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter ElseIf Abs(EntityY(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter ElseIf Abs(EntityZ(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter EndIf Next Add code between UpdateWorld and RenderWorld to check if any collisions occured between the bullets and anything else. Kill a badguy if the bullet hit one. For biter.bullettype = Each bullettype If CountCollisions(biter\entityhandle) > 0 badguyhit = EntityCollided(biter\entityhandle, 3) For badguysearch.badguytype = Each badguytype If badguyhit = badguysearch\entityhandle If badguysearch\state <> 5 badguysearch\state = 5 ;dead RotateEntity badguysearch\entityhandle, 0, 0, 90 TranslateEntity badguysearch\entityhandle, 0, -1, 0 Exit EndIf EndIf Next FreeEntity biter\entityhandle Delete biter EndIf Next |
| ||
The code archives are your friend, there is at least one FPS framework in there already. |
| ||
Thanks.... |
| ||
Updated the code I wrote above (removed a TON of errors) and improved it some. You can now shoot the bad guys. Here is the sample code in full: (with some temp objects for bullets and badguys) Graphics3D 800, 600 SetBuffer BackBuffer() Type bullettype Field entityhandle End Type Type badguytype Field entityhandle Field state End Type light = CreateLight() player = CreatePivot() camera = CreateCamera(player) CameraRange camera, .01, 250 level = LoadMesh("level.b3d") weapon1 = LoadMesh("pistol.b3d", camera) ;bulletmesh = LoadMesh("bullet.b3d") ;badguymesh = LoadMesh("badguy.b3d") bulletmesh = CreateCone():RotateMesh bulletmesh, 90, 0, 0:ScaleEntity bulletmesh, .1, .1, .1 badguymesh = CreateCylinder():ScaleEntity badguymesh, .4, 2, .25 HideEntity bulletmesh HideEntity badguymesh For iter = 1 To 10 badguy.badguytype = New badguytype badguy\entityhandle = CopyEntity(badguymesh) badguy\state = Rnd(1, 2) ;1=Guard 2=Search 3=Evade 4=Fire 5=Dead EntityType badguy\entityhandle, 3 EntityRadius badguy\entityhandle, .7, 2 Next MoveEntity camera, 0, .8, 0 MoveEntity weapon1, .1, -.15, .1 MoveEntity player, 20, 1, -20 For bgiter.badguytype = Each badguytype PositionEntity bgiter\entityhandle, Rnd(100)-50, 1, Rnd(100)-50 Next EntityType player, 1 EntityRadius player, .7, 2 EntityType level, 2 Collisions 1, 2, 2, 2 ;player to level Collisions 3, 2, 2, 2 ;badguy to level Collisions 4, 2, 2, 1 ;bullet to level Collisions 4, 3, 2, 1 ;bullet to badguy While Not KeyHit(1) If KeyDown(17) Then MoveEntity player, 0, 0, .1 If KeyDown(31) Then MoveEntity player, 0, 0, -.1 If KeyDown(30) Then MoveEntity player, -.1, 0, 0 If KeyDown(32) Then MoveEntity player, .1, 0, 0 TurnEntity player, 0, -MouseXSpeed()/5.0, 0 TurnEntity camera, MouseYSpeed()/5.0, 0, 0 If EntityPitch(camera) < -45 RotateEntity camera, -45, EntityYaw(camera), EntityRoll(camera) EndIf If EntityPitch(camera) > 45 RotateEntity camera, 45, EntityYaw(camera), EntityRoll(camera) EndIf MoveMouse GraphicsWidth()/2, GraphicsHeight()/2 If MouseHit(1) bullet.bullettype = New bullettype bullet\entityhandle = CopyEntity(bulletmesh) PositionEntity bullet\entityhandle, EntityX(weapon1, 1), EntityY(weapon1, 1), EntityZ(weapon1, 1) RotateEntity bullet\entityhandle, EntityPitch(weapon1, 1), EntityYaw(weapon1, 1), EntityRoll(weapon1, 1) EntityType bullet\entityhandle, 4 EntityRadius bullet\entityhandle, .01 EndIf For biter.bullettype = Each bullettype MoveEntity biter\entityhandle, 0, 0, 2 If Abs(EntityX(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter ElseIf Abs(EntityY(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter ElseIf Abs(EntityZ(biter\entityhandle, 1)) > 10000 FreeEntity biter\entityhandle Delete biter EndIf Next UpdateWorld For biter.bullettype = Each bullettype If CountCollisions(biter\entityhandle) > 0 badguyhit = EntityCollided(biter\entityhandle, 3) For badguysearch.badguytype = Each badguytype If badguyhit = badguysearch\entityhandle If badguysearch\state <> 5 badguysearch\state = 5 ;dead RotateEntity badguysearch\entityhandle, 0, 0, 90 TranslateEntity badguysearch\entityhandle, 0, -1, 0 Exit EndIf EndIf Next FreeEntity biter\entityhandle Delete biter EndIf Next RenderWorld Flip Wend |
| ||
That's it??!?! That's pretty short code for a FPS.... One other thing--how would I check to see if the "badguy" is not placed inside a wall of the level? Would I do this? : Before the main loop: If EntityCollide(badguy,level) ;I'm not really sure if those are the correct perimeters Goto setupbadguy ;Where setupbadguy is the "For...Next" loop in which the badguys are placed. EndIf Would this be correct, or does the code above already do that? Thanks for everything, though :) |
| ||
That's it??!?! That's pretty short code for a FPS.... Well, there isn't any code for enemy AI yet, but you could call it a First Person Shooter at this point I guess (although there's absolutely no bells & whistles). how would I check to see if the "badguy" is not placed inside a wall of the level? Well, there is no easy solution. The one you suggested would work per say, but wouldn't be very efficient (it may have to try 1268 times before it gets it right...). Also it wouldn't be very efficient because you are starting over from the beginning each time. A better solution would be to create a REPEAT-UNTIL loop that keeps trying until the current guy is placed.[pseudocode] Repeat MoveEntity badguy, Rnd(100), Rnd(100), Rnd(100) Until EntityCollided(badguy, level) = False [/pseudocode] Also, what if a badguy ends up on the OUTSIDE of a level? How does your code tell the INSIDE from the OUTSIDE? Or what about this scenario: B=badguy P=player outside +------------------+ | B B | | P | | inside | | +----+ | | | out| | outside | |side| | | | B | B | | +----+ | | B | +------------------| outsideThe badguy is inside the boundary of the game, but not in the playing area. One possible solution could be to start at a known good location (or several good locations) inside of the level and then randomly move the badguys around for a while with Collisions enabled. That way, they can't end up on the outside or within a wall. or you could just hard code in starting positions for the badguys, or you could create starting "zones" within your level by inserting huge hidden cubes in your level where the zones are. If the badguy isn't touching a zone (one of the hidden cubes) then try moving him somewhere else. I guess it's up to you. |
| ||
My map looks more like this:B = Badguy P = Player +---------------------+ | B | |------------------- | |B -------------------| |------------------- B| |------+ B | | P | +---------------------+ But I'll figure out the AI....I have an AI structure in a Space Invaders clone that I can work from....Thanks anyway, though :) And I think I will hardcode them - it will just be so much less complicated! :) |
| ||
the program didn't work...have you tested it yet? |
| ||
What program? Are you referring to the code I wrote above. If so, yes, I tested it, and it works perfectly fine on my machine. You would of course have to supply your own meshes for the level and weapon. And some of the numbers (like the MoveEntity commands) would have to be tweaked to fit your situation. |
| ||
a true fps game engine is a huge job that cannot be explained in a couple of lines of text. My own FPS engine has currently reached line 5908, include files not counted. And there is still no multiplayer inside. basicly you need an object structure for all meshes in your world. the object structure should contains a describtion string that will help you to handle special object jobs. So if your player steps close to a mesh that is described as "ammo", you can free the mesh, print "picked up some ammo" and add a number to the player_ammo variable. The easiest way to achieve this is to write a little world editor that will let you load a building mesh plus additional meshes as well as 3d-sounds. The editor will let you position, scale, rotate things, as well as to set all possible parameters (fx, alpha, pickable etc.) including said description string. It will then save a file that contains all the parameters of each mesh (and/or 3dsound etc.) including file-paths in a way that will allow your game engine to LOAD all the meshes and all parameters correctly. If you once have the Saving code, you can make a level-loader out of it relatively easy. The engine will then handle the description strings by seeking special triggering words, eg. "ammo", "medicine", "door" etc. It is recommended to parse the decription-string only once while loading the level and store the required information in arrays (eg. door()), together with individual counters for special arrays etc. Of course you can also use types instead of arrays, so you wont need counters, but it may complicate things as soon as you need to connect unrelated types by indexes. Enemies are a further chapter, true AI is pretty hard, but there are some collision avoidance examples around, with source. An alternative to AI is Waypoints. For this you only need to walk around in your level while recording your position frequently, then store this list of positions, just to apply it to an enemy in the engine. So the enemy will then walk along the points you have recorded, and only attack the player when he's visible to the enemy. This way your enemies even don't need collision since they follow the waypoints anyway. Multiplayer is yet a further job that will make things much more complicated. If you want multiplayer, you should implement it from beginning on to prevent dead ends. SaveGame is probably the trickiest thing, if you want SaveGame and LoadGame to work correctly (save any game State and restore it by the user) then you best implement this from beginning on as well, because it will become almost impossible if you didn't think of it from beginning on. And keep it up, Unreal wasn't made by a single person on a rainy afternoon. |
| ||
I only have two problems with the code above: one, the gun mesh I made is not in the lower-right hand corner, but in the middle of the right hand side. Another is that all collisions work, except for me and the walls....but...wait a minute! I just had an idea! Goooo me! |
| ||
the gun mesh I made is not in the lower-right hand corner Then modify this line to put it where you want it. Arrange your objects. MoveEntity weapon1, .1, -.15, .1 |