New to blitz, doing a raycaster

BlitzMax Forums/BlitzMax Beginners Area/New to blitz, doing a raycaster

LunaticEdit(Posted 2012) [#1]
So I picked up the BBMax demo last weekend and noticed that it build a .S (GCC assembler) file for my source code. That by itself pretty much had me sold because unlike most systems, BB actually builds real binaries, not bytecode stuff.. Just purchased the full version today :D

Anyway I've been hacking away at it happily for the last week and managed to produce this:




The third screenshot is of course raycasted, drawn pixel by pixel. Impressively it seems to run at a capped out 60fps. But there's one issue I'm having (mainly due to my n00bness I guess).. When I load the textures I load them as pixmaps and convert them to the proper byte format to match the screen. My math calcates at a specific X/Y on the screen, a specific X/Y pixel of a texture. I then set the value on the screen to match the texture. The problem is I have no idea how to do all 4 components at once, only one at a time:

				p1 = (y * pixmap.pitch) + (x Shl 2)
				p2 = (texY * wallTexture.pitch) + (texX Shl 2)
				If (side = 1) Then
					pixmap.pixels[p1]   = (t[p2] Shr 1)
					pixmap.pixels[p1+1] = (t[p2+1] Shr 1)
					pixmap.pixels[p1+2] = (t[p2+2] Shr 1)
				Else
					pixmap.pixels[p1]   =  t[p2]
					pixmap.pixels[p1+1] =  t[p2+1]
					pixmap.pixels[p1+2] =  t[p2+2]
				EndIf

As you can see, I have optimized as much as possible by doing a pre-calc and simply adding one.. but is there an easier way to simply set an entire 4-byte (DWORD) chunk instead of doing these components? (Note that I skip alpha as it's always full on).

Last edited 2012


col(Posted 2012) [#2]
Hiya and welcome!

Nice graphics! Looking like a neat raycaster you have going on there! A good exercise for any graphics/game programmer.

Did you know BlitzMax can access OpenGL directly with standard OpenGL commands to directly hit the hardware?

The answer to your question is:-
Yes, easily done by using an Int Ptr to point at the pixels

Local PixmapPtr:Int Ptr = Int Ptr pixmap.pixels
Local PixmapRGBA:Int  = PixmapPtr[ p1 ]


Last edited 2012


LunaticEdit(Posted 2012) [#3]
Yes, I'm aware. I'm doing this as a throw back to the TES:Arena days; I don't want to start off making a super complicated game; I've always done 2D games and want to do a raycasted one before getting head deep into true 3D. Besides I have 0 artistic skill for making polygons so it's a convenient excuse.

And thanks for the pointer info. I'm not completely familiar with the BB way of doing things yet. Now my screen writes are cut in 1/3 :D


matibee(Posted 2012) [#4]
Welcome!

We worked on optimising a ray tracer a couple of years ago. The individual pixel plot stuff was replaced with drawing vertical slices of the texture using DrawSubImageRect. It was pretty fast.

I'm stuck out with limited internet this weekend, but you'll find it here: www.matibee.co.uk/temp


LunaticEdit(Posted 2012) [#5]
I thought about doing that too, but it ended up being more code. With the pointer stuff it's blindingly fast, even on my older laptop; The other reason is because I'm about to add lighting and a few other features that will require other per-pixel calculations which will make a fast image blit not work. Hopefully I'll be able to post more screens up tonight as progress is made. I have to spend some time working on data and state management logic (all of the text is already multi-language supported, there are currently 3 language files I'm maintaining). Might even throw in the hud compass and put up a video on the youtubes... BBMax is fun :D


LunaticEdit(Posted 2012) [#6]
New screeny:


Now the raycaster is in it's own file and class(aka type). Data is now loaded via a file instead of static arrays. Added working compass, ability to set floor and ceiling textures, and a few more optimizations. Next up is to add in support for sprites.

I'm really happy about how easy it is to do things in blitz. It's not so much about a language issue (I can code in C just fine) so much as an API issue. Very good documentation and easy to work with.

Do also note that although I'm taking hints from TES:Arena, I'm NOT using their annoying input system. On this game you use normal FPS keys to move and strafe, and the mouse X motion to rotate. Of course this raycaster doesn't support looking up/down so no mouse X.. makes things easier to calculate with atan2 anyway :D

Last edited 2012


Yasha(Posted 2012) [#7]
This is super awesome, both in concept and execution.


LunaticEdit(Posted 2012) [#8]
http://www.youtube.com/watch?v=hT8v9kZTEEE


SystemError51(Posted 2012) [#9]
Holy Macaroni O_O. Quite possibly the most impressive thing I have seen for someone who just started.


LunaticEdit(Posted 2012) [#10]
Thanks... This is a game not a demo so progress is always good :) I'm working on the sprite engine now. Though I must point out that even though I am new to BlitzBasic I am by no means a beginner coder -- I write software for a living... just not games. I've done little demos here and there, the last ones being in XNA, but now I'm ready to sit down and actually finish something -- I've designed this game top to bottom and kept the development path as simple and easy on resources and time as possible while still being fun. I guess time will tell if I succeed :)


LunaticEdit(Posted 2012) [#11]
I present to you.. sprites :D











They can be positioned anywhere on the stage at any point (not just grid based). I also know the angle of the object in relation to the viewer -- I'm not using it at the moment but can in the future for 8-directional sprites or at stuff. Also, the sprites are 32-bit alpha-blended images.. I still plot per pixel but calculate the alpha blended RGB values so that simi-transparent objects are possible.

And here's a video:

http://www.youtube.com/watch?v=9_gHal4O4AM

Last edited 2012


matibee(Posted 2012) [#12]
That's looking good. What screen res are you running at?


LunaticEdit(Posted 2012) [#13]
640x480. It renders to a pixmap so technically I could run at any resolution. Been working on lighting effects and stuff. Don't let the initial screenshots fool ya, it's going to be a dark game :) Already have player lighting with torch style flickering :D


matibee(Posted 2012) [#14]
Do you plan on adding support for elevation changes, crushers / doors / elevators? This takes me back to the hours spent with doom editors :)


Matt Vinyl(Posted 2012) [#15]
Excellent stuff! Reminds me of one of my favourite games (not the 'theme' but the 'feel', if you get my drift.

http://en.wikipedia.org/wiki/Mercenary_(video_game)


Captain Wicker (crazy hillbilly)(Posted 2012) [#16]
Did you make this with miniB3D?
reminds me somewhat of minecraft. :D

Last edited 2012


BladeRunner(Posted 2012) [#17]
No, Cap, this is a raycaster, not one of the 3D-Modules around.


LunaticEdit(Posted 2012) [#18]
Yup, this is a raycaster. I've made some design choices that greatly limit the things it can do. Mainly for speed and calculation simplicity. The biggest thing is that there can only be one level of walls, and the ground must be flat. The walls must be exactly square and opaque as well. But now that I have lighting in, I'm adding a "light grid" that will define the brightness perceived by the player at that point in the map. As most of it will be played in dark caves with only the outside island itself being bright, a light grid will allow the transition properly, as well as allow interiors to be brightened via a light source instead of just the player's torch.

I've already removed the sword/shield aspect as I feel this will give the players too much security. It's going to be a dark game both in look and mood, and I do not believe killing rats and skeletons will work well in this environment -- besides, we've all killed enough of those things in other games.

Although you will be able to kill people, this is not a common occurrence and combat will be more personal than simply slashing them till they fall. The only real "creature" you have to worry about you can't actually fight. If it finds you it's game over -- no one knows what it looks like because the fact they are alive means they haven't seen it. You can hear it (if you are unlucky), and keep it at bay by lighting torches or barricading rooms or doors, but that's it -- and torches only last so long. The goal of the game does NOT involve killing the creature either; I'm not going to reveal much of the plot here, I'll leave it to the game to tell.

Just know, when you go into the caves, you may want to keep an ear out and stay far away from "it". The main game play will involve resource management (food/water/light), puzzles, and some quest-like sections.

I know the engine is limited but for this game I want to limit what I can do so I can instead concentrate on the game itself. If it does well I'll of course do a more powerful engine in future games.

Also, last night I finished implementing lua scripting; so now 100% of the game itself is done via map files and scripts, with only the engine being in BB. So if I ever want to port this to another device/language/etc all I have to do is convert the engine and use the same files.

Tonight or tomorrow I'll upload a video with commentary about what I've done so far and discuss some elements of the design and implementation - as well as reveal a little bit more about the game world; hopefully I'll start getting some viewers and suggestions as things progress. I'd like to start posting updates on my channel instead of spamming this forum.

Last edited 2012


matibee(Posted 2012) [#19]
Sounds really interesting and it's always good to see someone with a plan. Nice work.


LunaticEdit(Posted 2012) [#20]
There wouldn't happen to be a way to use inline assembler (specifically SSE2 opcodes) in blitzmax without doing an external module would there? I would assume not due to not knowing if you are compiling for 64-bit or 32-bit platforms, but figured I'd ask anywho...

Last edited 2012


col(Posted 2012) [#21]
Hiya,

Unfortunately not.

You can Import functions from seperate assembly and C/C++ files into your main file. And you can use inline assembly with your C/C++ code according to the MingW gcc compiler documentation. If you haven't already, then you'd need to download and install MingW using this guide to take advantage of compiling modules and your own C/C++ files.

You could modify BMax itself to take advantage of MingW gcc optimizations.

In BlitzMax/src/bmk/bmk_make.bmx
Lines 124 and 358, change

If opt_release cc_opts:+" -O2 -DNDEBUG"

to

If opt_release cc_opts:+" -O3 -DNDEBUG"

to switch on heavier optimizations. Quite a lot of the BRL core modules are C and can take advantage of this.
Save and close the bmk_make file, open the 'bmk.bmx' file in the same folder. In the 'Programs->Build Options' menu, make sure all options are OFF, then 'Build Only' to produce a new 'bmk.exe' in the /src folder. Copy this new bmk.exe into the BlitzMax/bin/ folder, saving the old one just in-case somethings gone wrong. Then 'Rebuild All Modules' to build all the modules in the BlitzMax/mod folder with the optimization above. You can now get some noticable speed gains already.

I've played with SSE/2/3 within C++ in BMax and something to note would be that after the above optimization, the C/C++ compiler could produce some pretty good code speed wise, which was already just as fast as when I was using SSE ( the compiler optimization will take advantage of SSE ). I'm sure some extra speed gains can be found with writing better code to take even more advantage, but I found that the biggest bottleneck was the function call overhead, and reducing that was a better optimization than using SSE. If you can write code to stay within a function thats using SSE for as long as possible then you can get some good speed gains, but to call a function, use SSE, then return and call it again etc, then the function call overhead negated the use of SSE.

Have fun :D

Last edited 2012


LunaticEdit(Posted 2012) [#22]
Good stuff, seems to have helped somehow. And I'm well aware of the hit taken when calling a function. I abstract things but only where necessary -- the raycasting method is a single function.

I really wish I could show you guys new screenshots, I have a guy doing the art (original screens used random images from google and didn't fit in well). It looks friggen amazing.

Right now I'm concentrating on doing the map editor -- there's starting to be more and more content, and with 35 textures and 15 maps it's hard to visualize in TextMate what's going on. I've pretty much gotten all of the limitations of the raycaster worked around via clever tricks (for example, even though the rays must hit a wall, I figured out a way to support outside areas and it look correct).

The other cool thing is that since the raycaster does it's thing on a variable-defined size on a pixmap, the map editor will be at a higher resolution and have a 'mini view' so you can see in real time exactly what the map will look like (in addition to the 2D editor view).

Anywho -- I can't wait until I'm able to send more screens!

[Edit]
OK I tried to do the same in windows, and the build modules menu options are both grayed out.. any ideas? I build the bmk properly after changes and copied over new EXE, but cannot get those two options to un-gray. Worked fine in OSX...

[Edit2]
Nevermind, helps if I RTFM and have MinGW :)

Last edited 2012


col(Posted 2012) [#23]
Sounds excellent!

[EDIT]
If you moved the whole raycaster function to Assembly, C or C++ and pass in any pixmaps needed as an array of address pointers then you could possibly stay inside that function and using SSE to do all the manipulations, and you might give you a bigger boost than you could imagine. Trial and error though as I'm sure already know :D
[/EDIT]

Looking forward to the new screenshots!

Last edited 2012


LunaticEdit(Posted 2012) [#24]
OK I couldn't help it.. here's some dumps from his facebook page... Keep in mind the compass has a white background because I'm using alpha transparency (he does pixel art) and he doesn't have a new copy of the EXE which will auto-alpha the color keyed transparent pixels. Yes, these are all in-game screenies, using an older version of my engine.







His version of the EXE doesn't support distant views, so sorry about the walls and darkness :) Again, new actual screens are a few days away.

I don't have his art update so my map data is trash.. But still, here's the engine rendering past the map area and supporting infinite rays. Also don't mind my crappy status bars -- I do code, not art :)



[Update]
OK now the map engine is in it's own source file as well, which allows me to do this:


Last edited 2012


Dabhand(Posted 2012) [#25]
I gonna be honest here... That's some mighty impressive stuff... Wish I had the time to delve into the logic behind all that... Great stuff! :)

Dabz


col(Posted 2012) [#26]
Hey Dabz,

Raycaster is actually quite simple and straight forward. Heres an example with source and a reasonable explanation of the concept. However, a good raycaster is something else :D

Theres a difference with making a raycaster and making a game. Raycasting is the software graphics engine putting stuff onto the screen - like writing a software version of your own gpu. Its the best exercise ever to put you on the right road to fully understand the design and concepts of 3d graphics. Making a game is still just as difficult as making any other game, and this coming along very well!

Very impressive!


LunaticEdit(Posted 2012) [#27]
That tutorial is pretty straight forward -- am I missing something though or does he not calculate aspect ratio? I do like the fact that he uses a positional vector instead of an angle -- I was debating on doing angles but decided vector is easier to rasterize with, which means it will run faster; besides, how hard is it to ArcTan2 the vector to get the angle :)

I've tried doing point lighting, and although it worked, it actually slowed the engine down a bit due to copious uses of square root and friends. I think for now I'll just use per-tile lighting instead. This project is starting to get some attention among my and the artists' friends on facebook; so if this game does well I'll work it in the next version of the engine.

Next engine (again, only if this game is successful) will use either OpenCL, or a pixel shader to raycast, I really don't see a need to use the video card's rasterization because it totally breaks the style and look of the game.

At the rate I'm going it looks like the map editor will be done sometime on friday (most of the game stuff will be a combination of lua scripts and supporting functions in the engine) so hopefully I can start pumping out some real screenshots soon as he does maps. Assuming things go to plan this entire weekend will be spent adding scripting features and gameplay elements.

And lastly, I noticed on the youtubes I posted, the 'demographic' of the viewers consists almost entirely of 25-45 year olds, which happens to be my target demographic for this game -- there's enough games for the younger folks out there ^_^

Oh, and now we are 1 sound guy away from a full team -- we have me for the engine/rules/overall design direction, the artist, and the designer (that handles all the nitty gritty details that make the game fun). Everyone is local which helps a lot :)

Last edited 2012


GW(Posted 2012) [#28]
Try this squareroot if you're getting slowdowns


Last edited 2012