Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / How's This For a Game Layout?

Author
Message
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 28th Apr 2007 08:23 Edited at: 26th Jan 2008 19:37
.
Zotoaster
19
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 28th Apr 2007 12:41
I think instead of Enemy_1_Controls() and Enemy_2_Controls(), you should just have one like Enemy_Controls(enemy). That makes much more sense, after all, this is what functions are for. But apart from that, it looks really neat

TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 28th Apr 2007 12:44
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 28th Apr 2007 21:05 Edited at: 26th Jan 2008 19:37
..
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 28th Apr 2007 21:55 Edited at: 28th Apr 2007 22:00
As a rule, I indent everything that is inside a programming 'block' - which I define as a number of lines which have a specific start and end.

This includes all loops, procedures (label: .. Return), functions (Function .. Endfunction), For..Next and so on.

I also indent Open File .. Close File too - anything to make reading the code better. (That's why my indenting utility DBA Tidy also indents Open File blocks).

The point is, if you are the only person who is ever going to see your code and you don't want to indent it then don't! It's your choice really. It's not set in stone that you have to do it.

But if you want to get someone else to help you solve a problem on the forum, then not indenting the code you post makes it harder for everyone to follow (including you) and may deter someone from helping.

Quote: "any ideas, anyone?"


Could be the IDE. Which one is it and have you seen if there any updates you can apply.

Two Player Mode

This uses exactly the same code as one player mode but at strategic positions in your code you would use something like:



TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 28th Apr 2007 22:47 Edited at: 26th Jan 2008 19:37
.......
Code Dragon
18
Years of Service
User Offline
Joined: 21st Aug 2006
Location: Everywhere
Posted: 28th Apr 2007 23:22
Quote: "Quote: "Could be the IDE. Which one is it and have you seen if there any updates you can apply."

What do you mean? :S "


There are multiple editors (IDEs). You're probably using the one that comes with DBP because I had the same problem before I installed the updates. Check the upgrades page for DBP and download them.

By reading this sentence you have given me brief control of your mind.
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 29th Apr 2007 04:38 Edited at: 26th Jan 2008 19:37
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 29th Apr 2007 05:53
Looking good so far!

If I had to suggest anything, it's the fact that you have two main program Do..loops when you only need one. (The only difference is a single line which calls the routine for player 2's controls).

All you need is a variable in the main menu such as NumPlayers which is set to 1 if it's a game against the computer and 2 if it's a 2 player game.

Your program then uses:



TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 29th Apr 2007 10:17 Edited at: 26th Jan 2008 19:38
...
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 30th Apr 2007 03:15
Quote: "Should they not have gosubs in them that don't return as well?"


Definitely not!

ALL subroutines start with a label and end with a Return. If you don't put the Return on the end, they aren't proper procedures. I'd not spotted that before now!

For example, you Gosub Setup and the Return on the end sends it back to the next line - Gosub Main_Menu.

What happens is that the calling (Gosub) line number is placed on something called the 'Stack'. The stack uses a FIFO system (First In First Out), so if no other procedures are called in the meantime, when you get to the Return, the number is removed from the stack and the PC (Program Counter) jumps back to the line immediately following the calling line.

If another procedure is called, then that line number is added to the stack. But, because the second proc's Return is always reached before the first one, it will always remove the correct number from the stack.

The problem is that the stack isn't of infinite size, so all values placed on there must be removed or you will eventually run out of stack space.

To continue with your program:

When you Gosub Main_Menu, the calling line number is added to the stack, but when you get there, you Gosub Single_Player so that line number is added to the stack.

At Single_Player, you call Single_Player_Load and that value is added to the stack. At the end of that proc the Return retrieves the value from the stack and jumps back.

However, as the first two Gosubs don't have an associated Return, the two values placed on the stack will never be removed.

A recipe for disaster!

If you Gosub any procedure (to a label), there must always be a Return for the Program Counter to get back to where it came from.

Never Gosub out of a procedure to one which it never returns from (like your Main_Menu).

Instead, trap the PC in Main_Menu until something has been chosen - then drop out using the Return. You end up with something like:



As you can see from that, you gosub the main menu at the start and stay there until the user selects a single or a two player game.

At which point, NumPlayers is set to either 1 or 2 and ExitMenuScreen set to 1. At which point, the Repeat..Until loop will be dropped out of and the PC will return back to drop into the main Do..Loop to start the game.

When the game ends, you simply Gosub Main_Menu again where once again it gets trapped until start game is chosen. This will repeat again and again forever - or Exit Game is selected from the menu.

And, you'll now understand that every value placed on the stack is removed, so you won't see any stack overflow errors!

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 30th Apr 2007 04:03 Edited at: 26th Jan 2008 19:38
....
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 30th Apr 2007 05:11 Edited at: 30th Apr 2007 05:18
Quote: "Instead of using a repeat...until loop, I made the program return if enter is pressed, that is fine right?"


No. As far as DB is concerned - and every other structured version of BASIC - a procedure (often also called a subroutine) has a defined start and end. As Do has a Loop, Repeat has an Until and If has an Endif.

In DB the start of a procedure is a label and the end is 'Return'.

These are clearly defined structures and you can't swap Endif for Return - or any of the others like you have done.

The Return cannot be placed anywhere else other than the end of a procedure either. Period!

That's how DB works and unfortunately you can't change the way it does it.

Your code has Ifs ending with Returns, Dos ending with Endifs and all sorts!

Here's what your procedure should look like structurally:



I say structurally because it's not the best way to do what you are trying to do...

Quote: "In Game_Over:, should I be using 'gosub Start' ... I really see no other way to get back to the beginning though."


At the point in your program your game is over, you use Gosub Main_Menu from inside the main loop. (Using Gosub you know it's going to eventually return back there to play another game - as long as all the Returns are present).

At the start of the Main_Menu procedure you use Gosub Game_Over if the value of GameJustEnded equals 1 - which displays the Game Over screen. Set GameJustEnded at the end of the game to prevent the Game over screen appearing when you first run the program and enter the main menu.

Like the Main_Menu, have the Game_Over procedure contain a Repeat...Until loop which exits only after a set amount of time or when the user presses a key.

At this point, PC hits the Return line and drops back to the Main_Menu procedure and displays the main menu. If they select to play, the Return drops back to the main loop and the game starts.

From there, with that layout everything goes round in circles for ever more...

Easy eh?

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 30th Apr 2007 08:53 Edited at: 26th Jan 2008 19:38
.....
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 30th Apr 2007 09:13
Quote: "There's a problem though...I need to reset all my variables before I can play another game"


Just time to cover this before I get some sleep - it's 7:05 am here!

OK, I expected this question - just didn't want to overload you with everything in one hit!

What you need is easy - just add another procedure called InitGame or similar. This is to initialise only the variables that are required to start/restart a game. (Leave the 'one-off' program start settings in the main Setup procedure).

You add a Gosub InitGame to the end of the Setup procedure and make sure that you don't have any duplicates in either.

Then, every time you start a game from the main menu, you only have to do a Gosub InitGame.

That's one of the beauties of procedural programs - you have a seperate procedure for every task and at any time you can drop another one in and add the Gosub(s) where necessary.

Tomorrow, I'll knock together a replacement Main_Menu for you, but for now I'm off to get a couple of hours sleep!

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 30th Apr 2007 12:31 Edited at: 26th Jan 2008 19:39
......
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 30th Apr 2007 17:14
No problem!

Quote: "I dunno what I can do for you"


Now you are an expert at procedural programming, never use Goto!

TDK_Man

TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 1st May 2007 02:41 Edited at: 1st May 2007 02:43
As promised, your re-written Main Menu procedure:



TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 1st May 2007 09:19 Edited at: 26th Jan 2008 19:39
.........
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 1st May 2007 09:38 Edited at: 26th Jan 2008 19:41
.......................................
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 1st May 2007 18:02 Edited at: 1st May 2007 18:03
Quote: "Why did you set Screen Height() and Width() to variables? Just a preference?"


No, it's just optimization.

The main menu snippet was written with DBP which is quite nippy, but after years of using the slower DBC (and many, many years before that writing software on much slower 8-bit machines), you get into the habit of squeezing the last bit of speed out of them.

Screen Width() and Screen Height() are functions which query the system every time it's used. It's quicker to access variables, so you use the function once and use the variable from then on. Admittedly, the speed gain isn't as much as pre-calculating often used calculations, but the principle is the same.

Using SW and SH also shortens the lines and makes them easier to read.

Quote: "I don't get how you used the scancode()"


ScanCode() simply returns a number when a key is pressed - otherwise it returns 0. Used in this way, the loop does nothing until a key is actually pressed. Without it, the program is continually printing things to the screen. With it, the screen is only updated if a key is pressed, so no flicker.

Normally, you use the format If condition = something for which the result is always binary True or False. The result can never be 'nearly' or 'maybe'.

If you leave the '= something' off the end, a true result is implied - DB assumes you are testing for true - in other words, any value other than zero.

So, If Scancode() just means If Scancode() = True - or the same as using If Scancode <> 0.

Quote: "Why do you stack some commands as opposed to 1 per line?"


Personal preference - and a touch of laziness!

Don't you think it's easier to see the whole of a function on the screen at the same time without having to scroll up and down to see the beginning and end?

Quote: "Can you explain what the 'Case' and 'EndCase' do"


Select and Case are a convenient alternative to lots of If..Then statements. In plain English, read it as 'SELECT a variable. In the CASE of it being X, then do X. In the CASE of it being Y then do Y' - and so on. An example:

Say that A can be a number between 1 and 5 and you want to print the current value of A:



Using Select..Case:



Not exactly an example which demonstrates Select/Case is any better than If..Endif but shows how it works.

Quote: "You like to multiply the screen height/width to adjust the word positions instead of add/subtract them. Does it matter?"


I don't remember changing anything from your version. To be honest, as they don't change I would rather have used fixed X and Y screen positions for the Text command, but not knowing if you were going to have user-selectable screen resolutions in the future this wasn't possible.

Quote: "The text didn't show up at first because it wasn't in the loop!"


It shouldn't be! Don't change anything as it works fine as it is. If it doesn't for you then the reasons are elsewhere. To start with, are you using the latest upgrade of DBPro?

As I don't have the media, I had to write the main menu procedure as a stand-alone piece of code and it worked perfectly for me. It might be something somewhere else in your program that is causing the problem. I've added another Sync which should work.

Inside the Repeat..Until loop, everything is repeated - including printing to the screen - whether it's needed or not.

My version printed the options to the screen because inside the loop updates are only done when a key is pressed. In your version, your changes simply negate the reason for having the If ScanCode() block.

I did however forget to include the Player Load section at the end of main_menu. That's now done.

Quote: "In the same lines of this problem, did you intend the code to flash white for each button when selected, because it does. How would I make it stay white?"


It only does this because you've moved some of the Text statements inside the loop!

Quote: "Lastly, why is this better than my old one"


Because it works!

Here's your whole program so far. I can't however run it. If you have any further problems, you might want to attach the media to your next post...



TDK_Man

TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 1st May 2007 19:50
Quote: "I can't visualize the program's 'path' very well."


Does this rough sketch help?



TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 2nd May 2007 07:32 Edited at: 26th Jan 2008 19:40
................
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 2nd May 2007 21:38
OK, it's sorted - well the main problem anyway...

The procedure I did for you worked fine - it was your use of the backdrop which was causing the problem, so I've disabled it.

Backdrop is used with a 3D program and as your program is 2D then it's not required - all it does is blank any 2D text off the screen - as you discovered!

If you are thinking that disabling it will cause the 'House Of Mirrors' effect, don't worry - there's a command called Set Sprite which you use. This simply tells your sprite to restore it's own background when it moves.

This is turned off by default - that's why you got the nasty effect. Alternatively, you can use CLS in the loop, but that can cause flicker.

There's still plenty to do, but here's the working version so far:



TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 3rd May 2007 05:33 Edited at: 26th Jan 2008 19:40
.....
.
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 3rd May 2007 08:18
Quote: "howcome my sync in always 60, no matter if I change it or not?"


You mean the fps always shows 60 - even if you change it to a value greater than 60?

If so, try using Sync Rate 30. Does it then show around 30 fps? If so then it sounds like you may have a flat screen and it can't do more than 60 or so screen refreshes per second.

I just tried setting the Sync Rate to 80 and it gave me 76/77 fps.

Quote: "now it flickers sometimes"


When - on the menu or while playing the game? It doesn't flicker for me at all.

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 3rd May 2007 10:57 Edited at: 26th Jan 2008 19:40
.
.
.
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 3rd May 2007 15:40
Quote: "Any ideas on how to give the FPS a boost?"


One word - optimization!!

Your code needs to be efficient and not do things it doesn't need to. You shouldn't use calculations when they are not required and you should only call procedures when necessary - ie using timers.

These things only come with experience. As you get better at programming, you'll learn better ways of doing things.

You also have to remember that others might have the opposite problem - for them, your program might run too fast!

The point is, on your machine, if it's capping at 60fps then you aren't going to see any gains in speed from any optimizing you do anyway.

What are your machine's specs - CPU, memory, GFX card and OS?

TDK_Man

Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 4th May 2007 06:52 Edited at: 26th Jan 2008 19:40
..
.
.
indi
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: Earth, Brisbane, Australia
Posted: 4th May 2007 10:50
you can fake sprites with 3d panels, eliminating the whole sprite libraries.
you gain all of the 3d element to that component as well as shaders.

TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 4th May 2007 18:18 Edited at: 4th May 2007 18:38
To be honest, DB's 2D commands are reknown for being slow, but they are fast enough to use - especially while learning the language.

As Indi says, if you hit a problem you can't get round then switching to 3D and faking sprites is an option.

I don't use DBPro very often - so I'm not sure technically how pro differs (if anything) from classic in the 2D department. And incompatibilities make it difficult to run a DBC 2D program in Pro to test the difference.

I've taken a look at your program in a bit more detail and made a few changes to see if I could improve the speed. But until you try it, I don't know if they will make any difference on your machine.

First of all, your sprite images are huge! 1 meg images for both player bases is a bit OTT, so I resized them. In DBC they would have had an effect - in DBP I'm not so sure.

I've also re-written the bullet firing side of things - it now fires 'x' multiple bullets by tapping the space bar.

I've attached what I have so far for you to look at. I basically started from scratch - modifying your code and adding it as I went along. But I ran out of time and had to work on something else, so you can continue adding to it if you like.

Quote: "Also btw, when I took out the 'Set Sprite' commands, my fps went up a lot"


Possibly a side effect of huge sprite images?...

I did a 2D sprite space invaders - I'll see if I can dig it out. Testing it on your system - which looks to be OK by the way - will possibly show any problems with it, regarding flickering.

[Edit] OK - found it. Download it here:

DB Space Invaders (1MB)

TDK_Man

Attachments

Login to view attachments
Kiefer Greenspan
20
Years of Service
User Offline
Joined: 11th May 2004
Location: NY
Posted: 5th May 2007 08:56 Edited at: 26th Jan 2008 19:41
...............................

Login to post a reply

Server time is: 2024-09-26 22:57:38
Your offset time is: 2024-09-26 22:57:38