Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Help with keyboard and graphics.

This thread is locked; no one can reply to it. rss feed Print
 1   2   3 
Help with keyboard and graphics.
konedima
Member #6,241
September 2005

I have two questions here, so I'll address them individually.

1: In the game I am making, you need to press a key to fire a bullet. When I press the key though, it fires multiple bullets at once (which is bad because they need to be fired individually).
if (key[KEY_D]) player1newbullet();
Is the code I use to trigger firing a bullet. What's the best way to fix it?

2: My game runs at 16 bit colour depth (it always has, purely because I feel like it). The graphics for use in game are stored as bitmaps. When I try using 16-bit bitmaps in-game (they are 16-bit because there is no point in them being any more detailed, it won't show any more detail at 16-bit colour, obviously) they just show up as black squares the size of the bitmap. I can fix it by saving the bitmaps at any other colour depth (or indexed colour, which can be handy for the ones that only have a few different colours). As I said, I don't want to go to all the hassle of converting all my bitmaps to a different colour depth and since my game is skinnable by the end user I don't want them to have problems.
This sets the graphics mode:

set_color_depth(16);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0;

This loads a graphic:

BITMAP *background;
background = load_bitmap("background.bmp", NULL);

And this displays that graphic:
draw_sprite(buffer,background,0,0);
Finally, since I'm using double buffering, this creates the temporary buffer:
buffer = create_bitmap(640,480);

Any and all help with these problems would be greatly appreciated.
Thanks, Konedima.

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

DanielH
Member #934
January 2001
avatar

1bool kb = false;
2 
3if ( key[ KEY_D ] )
4{
5 if ( !kb )
6 {
7 // just pressed
8 }
9 
10 kb = true;
11}
12else
13{
14 if ( kb )
15 {
16 // just released
17 }
18 
19 kb = false;
20}

Mark Oates
Member #1,146
March 2001
avatar

if you're using c++:

1#include <vector>
2 
3using namespace std;
4 
5////////////////////////////////////////////////////////////////////////////////
6////////////////////////////////////////////////////////////////////////////////
7 
8class control_button_class
9{
10public:
11 bool pressed;
12 bool just_pressed;
13 bool just_released;
14
15 int key_name;
16
17 control_button_class(int al_key_n)
18 {
19 key_name = al_key_n;
20 pressed = false;
21 just_pressed = false;
22 just_released = false;
23 }
24
25 void set_key(int al_key_n)
26 {
27 key_name = al_key_n;
28 }
29 
30 void update()
31 {
32 just_pressed = false;
33 just_released = false;
34
35 if (!key[key_name] && pressed) { just_released = true; }
36 if (!key[key_name])
37 {
38 pressed = false;
39 just_pressed = false;
40 }
41
42 if (key[key_name] && !pressed) { just_pressed = true; }
43 if (key[key_name])
44 {
45 pressed = true;
46 just_released = false;
47 }
48 }
49};
50 
51 
52class controls_manager_class
53{
54public:
55 vector<control_button_class> button;
56
57 controls_manager_class()
58 {
59 }
60
61 void add_button(int al_key)
62 {
63 bool button_used = false;
64 for (int i=0; i<button.size(); i++)
65 {
66 if (button<i>.key_name == al_key) button_used = true;
67 }
68 if (!button_used) button.push_back(control_button_class(al_key));
69 }
70
71 void update()
72 {
73 for (int i=0; i<button.size(); i++) button<i>.update();
74 }
75
76 bool pressed(int al_key)
77 {
78 for (int i=0; i<button.size(); i++)
79 {
80 if (button<i>.key_name == al_key) return button<i>.pressed;
81 }
82 add_button(al_key);
83 return false;
84 }
85
86 bool just_pressed(int al_key)
87 {
88 for (int i=0; i<button.size(); i++)
89 {
90 if (button<i>.key_name == al_key) return button<i>.just_pressed;
91 }
92 add_button(al_key);
93 return false;
94 }
95 
96 bool just_released(int al_key)
97 {
98 for (int i=0; i<button.size(); i++)
99 {
100 if (button<i>.key_name == al_key) return button<i>.just_released;
101 }
102 add_button(al_key);
103 return false;
104 }
105 
106};
107 
108 
109controls_manager_class input_controller;
110 
111#define pressed(x) input_controller.pressed(x)
112#define just_pressed(x) input_controller.just_pressed(x)
113#define just_released(x) input_controller.just_released(x)

it's easy to use! just

if (just_pressed(KEY_D)) fire_bullet();

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Paul whoknows
Member #5,081
September 2004
avatar

konedima, your avatar rocks!

____

"The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner.

Kitty Cat
Member #2,815
October 2002
avatar

int k = (keypressed() ? (readkey() >> 8) : 0);
...
if(k == KEY_D)
    player1newbullet();

:P Why do you people keep insisting on using key[] in a way it wasn't designed for?

Also, the ordering of how you call set_gfx_mode and load_bitmap is very important. When using Allegro properly, there's really no reason to restrict to a specific color depth, unless you're using palette effects (which you're obviously not). You should try to use desktop_color_depth() whenever possible, otherwise you may get a bad speed hit from color conversions.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

I'm having mixed success with your suggestions.
And by mixed, I mean none.

DanielH: That does nothing, basically. The bullets fire in shorter bursts but I need it to be that only one fires.

Mark Oates: When I put that in (where I thought it should be, I'm pretty new to C++ but I think I did it right), and I press the key, it doesn't do anything at all.

Paul whoknows: Thanks!

Kitty Cat: For the keys, that doesn't work. Like Mark's, the key presses don't do anything. And I did set it the colour depth to desktop_color_depth(), thanks for the advice. It's not any faster (it was never particularly slow, and I have to slow it down to keep it at a decent speed) and it doesn't fix my graphics problem. It still displays my 16 bit bitmaps as black.

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

Kitty Cat
Member #2,815
October 2002
avatar

You're going to have to show more code, then.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

How much do you want?

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

Kitty Cat
Member #2,815
October 2002
avatar

Initialization (where you call set_gfx_mode, create_bitmap, load_bitmap, and stuff), and your input routine.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

These are missing some parts inbetween, but all these bits are shown in the order they appear in the code.

BITMAP *ball;
BITMAP *background;

Same for the rest of the graphics.

int player1size;
int player1score;

Same for the rest of the global variables.

void loadgraphics();
void scoreforone();

Same for the rest of the functions.

1// Main section
2int main() {
3 // Set up all the Allegro functions
4 allegro_init();
5 install_keyboard();
6 set_color_depth(desktop_color_depth());
7 if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0)!=0) {
8 allegro_message("Unable to set graphics mode.",allegro_error);
9 }
10 set_window_title("War Pong");
11 set_config_file("warpong.cfg");
12 // Set the random seed
13 srand(time(NULL));
14 // Create bitmap for buffer to go into
15 buffer = create_bitmap(640,480);
16 // Run loading functions
17 setvars();
18 loadgraphics();
19 makebats();
20 scoreforone();
21 scorefortwo();
22 resetbullets();
23 // Create new ball for start of new game
24 newball();
25 // Go to the game loop
26 maingame();
27}
28END_OF_MAIN()

That's the entire main loop.

1// Player 1 input and display
2void playerone(){
3 draw_sprite(buffer,player1bat,0,player1y);
4 if (key[KEY_W]) player1y = player1y - 4;
5 if (key[KEY_S]) player1y = player1y + 4;
6 if (key[KEY_D]) player1newbullet();
7 }
8// Player 2 input and display
9void playertwo(){
10 draw_sprite(buffer,player2bat,620,player2y);
11 if (key[KEY_UP]) player2y = player2y - 4;
12 if (key[KEY_DOWN]) player2y = player2y + 4;
13 if (key[KEY_LEFT]) player2newbullet();
14 }
15 
16// General (non-player specific) input
17void generalinput() {
18 if (key[KEY_ESC]) win = 3;
19}

Those are the only functions that take keyboard input.
If you need any more just ask.

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

Kitty Cat
Member #2,815
October 2002
avatar

Unless you're disabling color conversions, I see no reason why your graphics come out black. Though I can't see the code where you actually load the graphics.

As for input, you're mixing your logic and drawing. Something like this would work:

1// General input
2void generalinput(int k)
3{
4 // Player 1
5 if (key[KEY_W]) player1y = player1y - 4;
6 if (key[KEY_S]) player1y = player1y + 4;
7 if (k == KEY_D) player1newbullet();
8 
9 // Player 2
10 if (key[KEY_UP]) player2y = player2y - 4;
11 if (key[KEY_DOWN]) player2y = player2y + 4;
12 if (k == KEY_LEFT) player2newbullet();
13 
14 // General
15 if (k == KEY_ESC) win = 3;
16}
17 
18void drawthings()
19{
20 draw_sprite(buffer,player1bat,0,player1y);
21 draw_sprite(buffer,player2bat,620,player2y);
22}
23...
24while(playing) {
25 while(speed_timer > 0) {
26 --speed_timer;
27 while(keypressed()) {
28 int k = readkey() >> 8;
29 generalinput(k);
30 }
31 }
32 
33 drawthings();
34}

Note that player up-down movement will be continuous while the key is held down. If you don't want that, do this instead:

    if (k == KEY_W) player1y = player1y - 4;
    if (k == KEY_S) player1y = player1y + 4;
...
    if (k == KEY_UP)   player2y = player2y - 4;
    if (k == KEY_DOWN) player2y = player2y + 4;

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

While I have a look at that keyboard code here's an example of loading the graphics:

ball = load_bitmap("ball.bmp", NULL);
background = load_bitmap("background.bmp", NULL);

They're all like that.

Edit: I generally don't work well with code other than my own, and when I implemented your changes, I can't seem to get it to work (and when I do, it just freezes on a black screen). This is what I've got:

1void maingame(){
2 while (win <= 0){
3 // Draw objects that always appear before we get into the stuff that moves
4 draw_sprite(buffer,background,0,0);
5 draw_sprite(buffer,logo,65,60);
6 draw_sprite(buffer,scoreone,40,190);
7 draw_sprite(buffer,scoretwo,400,190);
8 // Now the stuff that moves
9 workbullets();
10 ballmove();
11 while(playing){
12 while(speed_timer > 0) {
13 --speed_timer;
14 while(keypressed()) {
15 int k = readkey() >> 8;
16 input(k);
17 }
18 }
19 
20 players();
21 }
22 dodisplay();
23 // Now we rest to make sure the game doesn't run too fast
24 rest(10);
25 }
26}
27 
28void input(int k){
29 // Player 1
30 if (key[KEY_W]) player1y = player1y - 4;
31 if (key[KEY_S]) player1y = player1y + 4;
32 if (k == KEY_D) player1newbullet();
33 // Player 2
34 if (key[KEY_UP]) player2y = player2y - 4;
35 if (key[KEY_DOWN]) player2y = player2y + 4;
36 if (k == KEY_LEFT) player2newbullet();
37 // General
38 if (k == KEY_ESC) win = 3;
39}
40void players(){
41 // Draw the bats
42 draw_sprite(buffer,player1bat,0,player1y);
43 draw_sprite(buffer,player2bat,620,player2y);
44 // Make sure the bats don't go off screen
45 if (player1y < 0) player1y = 0;
46 if ((player1y + player1size) > 480) player1y = (480 - player1size);
47 if (player2y < 0) player2y = 0;
48 if ((player2y + player2size) > 480) player2y = (480 - player2size);
49}

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

Kitty Cat
Member #2,815
October 2002
avatar

You're mixing logic and drawing again. And don't use rest() to time the game. The FAQ is your friend.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

Now I'm getting somewhere (it works!) but the bats (using w,s,up,down) move very choppily and pressing esc or either of the shoot buttons don't register at all.

This is what I got:

1void maingame(){
2 LOCK_VARIABLE(speeder);
3 LOCK_FUNCTION(increment_speeder);
4 install_int_ex(increment_speeder, BPS_TO_TIMER(60));
5 while (win <= 0){
6 // Draw objects that always appear before we get into the stuff that moves
7 draw_sprite(buffer,background,0,0);
8 draw_sprite(buffer,logo,65,60);
9 draw_sprite(buffer,scoreone,40,190);
10 draw_sprite(buffer,scoretwo,400,190);
11 while(speeder > 0) {
12 speeder--;
13 while(keypressed()) {
14 int k = readkey() >>8;
15 input(k);
16 }
17 workbullets();
18 ballmove();
19 players();
20 }
21 drawbats();
22 dodisplay();
23 // Now we rest to make sure the game doesn't run too fast
24 rest(10);
25 }
26}
27 
28void input(int k){
29 // Player 1
30 if (key[KEY_W]) player1y = player1y - 4;
31 if (key[KEY_S]) player1y = player1y + 4;
32 if (k == KEY_D) player1newbullet();
33 // Player 2
34 if (key[KEY_UP]) player2y = player2y - 4;
35 if (key[KEY_DOWN]) player2y = player2y + 4;
36 if (k == KEY_LEFT) player2newbullet();
37 // General
38 if (k == KEY_ESC) win = 3;
39}
40void players(){
41 // Make sure the bats don't go off screen
42 if (player1y < 0) player1y = 0;
43 if ((player1y + player1size) > 480) player1y = (480 - player1size);
44 if (player2y < 0) player2y = 0;
45 if ((player2y + player2size) > 480) player2y = (480 - player2size);
46}
47void drawbats(){
48 // Draw the bats
49 draw_sprite(buffer,player1bat,0,player1y);
50 draw_sprite(buffer,player2bat,620,player2y);
51}

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

LennyLen
Member #5,313
December 2004
avatar

Change:
int k = readkey() >>8;

to:

int k = readkey() << 8;

konedima
Member #6,241
September 2005

Sorry, that doesn't work. Any other ideas?

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

LennyLen
Member #5,313
December 2004
avatar

Oops, my fault for misreading the manual. That was the test for ALT + key.

What happens if you change it to:
int k = readkey();

and then change the other checks to (for example):
if ((k >> 8) == KEY_ESC) win = 3;

Kitty Cat
Member #2,815
October 2002
avatar

I don't see why the shoot buttons and escape don't work. Have you traced them to see that they behave properly? As for the choppiness, that's probably because you're moving four pixels at a time. And you're using rest(10);, which is probably causing timing issues. Instead, use:

while(speeder <= 0)
    rest(1);

So it only rests when you have time to wait.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

konedima
Member #6,241
September 2005

For whatever reason, now it is registering those key presses. And when I mean moving the bats is choppy, I mean that before I did all this they moved smoothly. And faster.

Sorry if I sound like I'm whining.

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

HardTranceFan
Member #7,317
June 2006
avatar

[edit]
Hmm, from a reread of your post, I'm not sure it means it all works or there are still problems.
[/edit]

konedima, does the following make any difference to the choppiness?

1void maingame(){
2 int nspeed, k; // <------ added
3 LOCK_VARIABLE(speeder);
4 LOCK_FUNCTION(increment_speeder);
5 install_int_ex(increment_speeder, BPS_TO_TIMER(60));
6 while (win <= 0){
7 // Draw objects that always appear before we get into the stuff that moves
8 draw_sprite(buffer,background,0,0);
9 draw_sprite(buffer,logo,65,60);
10 draw_sprite(buffer,scoreone,40,190);
11 draw_sprite(buffer,scoretwo,400,190);
12 
13 // give some up some processing time if none is needed
14 if (speeder == 0) // <------ added
15 rest(1); // <------ added
16 nspeed = speeder; // <------ added
17 speeder = 0; // <------ added
18 while(nspeed > 0) { // <------ changed
19 nspeed--;
20 while(keypressed()) {
21 k = readkey() >>8; // <------ changed
22 input(k);
23 }
24 workbullets();
25 ballmove();
26 players();
27 }
28 drawbats();
29 dodisplay();
30 }
31}

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

konedima
Member #6,241
September 2005

I'm good at not being clear :).

All the input issues are fixed. The problems I have are that the bat (and sometimes the bullet) movement is very choppy (bullets appear to move back and forth occasionally) and that 16-bit bitmaps still don't work.

HardTranceFan, your code doesn't help, thanks anyway.

I've changed the code since I last posted it - I've moved all the drawing operations into one function, and out of their logic functions. Here's the main game loop:

1void maingame(){
2 int nspeed, k;
3 LOCK_VARIABLE(speeder);
4 LOCK_FUNCTION(increment_speeder);
5 install_int_ex(increment_speeder, BPS_TO_TIMER(60));
6 while (win <= 0){
7 if (speeder == 0)
8 rest(1);
9 nspeed = speeder;
10 speeder = 0;
11 while(nspeed > 0) {
12 nspeed--;
13 while(keypressed()) {
14 k = readkey() >>8;
15 input(k);
16 }
17 workbullets();
18 ballmove();
19 players();
20 }
21 quickdisplay();
22 }
23}

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

HardTranceFan
Member #7,317
June 2006
avatar

If you attach the complete source, then some of the allegroids could have a look. It could be that you've overlooked an issue elsewhere in your program.

Or attach the binary and see if it occurs on other machines.

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

konedima
Member #6,241
September 2005

I'm weirdly overprotective of my source code (espcially since I plan on releasing it as open source when it's done). I could post it if I really had to, but I'd rather look for other alternatives. The only thing I can think of is that as mentioned before, the bats are moved up four pixels at a time (actually now it's eight). The program was probably running at a faster framerate before because I only had a rest(10) to slow it down, so that could have been it. I don't know how to fix it because if they move any slower, they won't move nearly fast enough.

Something else I've noticed during testing of the latest code is that if you shoot a bullet while moving the bat (by holding the key down), the movement stops until you let go and press down again. Is there any way to fix that?

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

HardTranceFan
Member #7,317
June 2006
avatar

Quote:

Something else I've noticed during testing of the latest code is that if you shoot a bullet while moving the bat (by holding the key down), the movement stops until you let go and press down again. Is there any way to fix that?

Ahhh, I just noticed you have a :

while(keypressed()) 
{
  k = readkey() >>8;
  input(k);
}

So while you hold down a key, it's going to remain within that loop until the key is released. It will update the co-ordinates, but not draw them to the screen.

Change the while to an if. I suspect this may fix your visual problem.

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

konedima
Member #6,241
September 2005

Nope, it doesn't.

War Pong HD! Every time you don't download it, a kitten of hope dies in my heart. Please, save the imaginary kittens.
http://warpong.sourceforge.net

 1   2   3 


Go to: