Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » KrampusHack 2016

Credits go to amarillion, Elias, Eric Johnson, and SiegeLord for helping out!
This thread is locked; no one can reply to it. rss feed Print
KrampusHack 2016
bamccaig
Member #7,536
July 2006
avatar

Eric Johnson
Member #14,841
January 2013
avatar

The program only freezes if I call PopulateAvatars(); otherwise, it doesn't freeze. Anyone else used Edgar's code successfully? Maybe it's just me screwing up.

bamccaig
Member #7,536
July 2006
avatar

Debug away!

Quote:

#SelectExpand
1 if (atlas) { 2 if (!al_is_sub_bitmap(atlas)) {
3 al_destroy_bitmap(atlas);
4 } 5 } 6
7 if (!atlas) {
8 atlas = al_create_bitmap(total_width , total_height); 9 }
10 if (!atlas) {
11 printf("Failed to create %d x %d atlas.\n" , total_width , total_height); 12 return false; 13 } 14 15 16 bool fail = false; 17

I tried to do a quick review for bugs, but I have to go get the dishes done before my dearest returns! <3 I noted the above. I don't know WTF it's for, but it appears to destroy the bitmap without resetting the pointer and then attempts to use the pointer again later... Seems sloppy and probably a bug. That said, I'm assuming that would only occur if you called the function twice. The best way to figure it out is an interactive debugger.

Eric Johnson
Member #14,841
January 2013
avatar

I am pressed for time, so I decided against using Edgar's code. Sorry, Edgar!

My gift is as finished as it will ever be now. I would like to submit it. I do not see an option to upload attachments to private messages though. :o

[EDIT]
I'll just use another site to upload it and send the gift as a link, I guess.

Edgar Reynaldo
Member #8,592
May 2007
avatar

That's odd. All it does is allocate and load bitmaps. It could be making the large Atlas a memory bit.ap if you do t have a large enough texture. I'll explore later when I get home. You're using the second version I provided right?

Typos courtesy of my phone and my clumsy thumbs.

Eric Johnson
Member #14,841
January 2013
avatar

Yeah, I'm using the second version. If I have time, I'll give it another go tomorrow sometime.

amarillion
Member #940
January 2001
avatar

Spent about 20 hours so far, and Max added another 4 hours or so for graphics.

--
Martijn van Iersel | My Blog | Sin & Cos | Tegel tilemap editor | TINS 2017

Edgar Reynaldo
Member #8,592
May 2007
avatar

At 12*(160+2), the texture is 1944 pixels wide. Most modern video cards should be able to create a texture that is 2048x2048 at least. Just add in a check for :

if (al_get_bitmap_flags(bitmap) & ALLEGRO_MEMORY_BITMAP)) {
   printf("Atlas is a memory bitmap\n");
}

Edit, the code could be modified to make a 6x2 or 4x3 atlas instead, without too much fuss.

Update:
I've been spending more time on graphics than on coding. If I ever finish, at least it should look good.

Mark Oates
Member #1,146
March 2001
avatar

Workin workin workin! My graphics don't look too bad. I need to make my level so I can start playing the game!

I've been spending more time on graphics than on coding. If I ever finish, at least it should look good.

Cool! 8-)

Eric Johnson
Member #14,841
January 2013
avatar

I wrote a quick program to test your avatar pack, Edgar. Here's what I have:

#SelectExpand
1#include <iostream> 2 3#include "Avatars.hpp" 4 5#include <allegro5/allegro.h> 6#include <allegro5/allegro_image.h> 7 8using std::cout; 9 10int main(void) { 11 12 if (!al_init()) { 13 14 cout << "Error: failed to initialize Allegro!\n"; 15 16 return -1; 17 } 18 19 if (!al_init_image_addon()) { 20 21 cout << "Error: failed to initialize image addon!\n"; 22 23 return -1; 24 } 25 26 ALLEGRO_TIMER *timer = al_create_timer(1.0 / 60.0); 27 ALLEGRO_DISPLAY *display = al_create_display(800, 600); 28 ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue(); 29 30 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 31 al_register_event_source(event_queue, al_get_display_event_source(display)); 32 33 bool running = true; 34 bool render = true; 35 36 // Set path stuff. 37 38 ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); 39 40 al_append_path_component(path, "./"); // Directory from which binary was executed. 41 42 al_change_directory(al_path_cstr(path, '/')); 43 44 al_destroy_path(path); 45 46 if (!PopulateAvatars()) { 47 48 cout << "Error: failed to populate avatars!\n"; 49 50 return -1; 51 } 52 53 al_start_timer(timer); 54 55 while (running) { 56 57 ALLEGRO_EVENT event; 58 59 al_wait_for_event(event_queue, &event); 60 61 if (event.type == ALLEGRO_EVENT_TIMER) { 62 63 render = true; 64 65 static unsigned int ticks = 0; 66 67 ++ticks; 68 69 cout << "Ticks = " << ticks << "\n"; 70 71 if (ticks >= 300) { 72 73 // End the program after five seconds. 74 running = false; 75 } 76 } 77 78 if (render && al_is_event_queue_empty(event_queue)) { 79 80 render = false; 81 82 // Clear to red. 83 al_clear_to_color(al_map_rgb(255, 0, 0)); 84 85 al_flip_display(); 86 } 87 } 88 89 al_destroy_timer(timer); 90 al_destroy_display(display); 91 al_destroy_event_queue(event_queue); 92 93 return 0; 94}

The above outputs the following:

Quote:

Failed to load avatar data/avatarpacks/avatarpack160/16609_TakaakiFurukawa_avatar_160x160.png
Error: failed to populate avatars!

I took a look and found that Takaaki Furukawa's avatar had a capital "K" in each of its avatar files. Making that a lower-case "k" fixed it. However, now the screen just appears black (it still updates and ends after 5 seconds like it should though). I don't even bother to call GetAvatar().

Here's the code from Avatar.cpp that I'm using:

#SelectExpand
1 2 3 4#include "Avatars.hpp" 5#include <cstdio> 6 7 8const char* avatar_names[NUM_AVATARS] = { 9 "358_Elias_avatar", 10 "940_Amarillion_avatar", 11 "1666_Derezo_avatar", 12/// "3110_MiguelFire_avatar", 13 "3861_GullRaDriel_avatar", 14 "5337_mc_avatar", 15 "6152_Onewing_avatar", 16 "7827_SiegeLord_avatar", 17 "8592_EdgarReynaldo_avatar", 18 "8643_Vanneto_avatar", 19 "1146_MarkOates_avatar", 20 "14841_EricJohnson_avatar", 21 "16609_TakaakiFurukawa_avatar" 22}; 23 24 25 26ALLEGRO_BITMAP* avatars160[NUM_AVATARS] = {0}; 27ALLEGRO_BITMAP* avatars64[NUM_AVATARS] = {0}; 28ALLEGRO_BITMAP* avatars32[NUM_AVATARS] = {0}; 29ALLEGRO_BITMAP* avatars32bw[NUM_AVATARS] = {0}; 30 31ALLEGRO_BITMAP* avatar_atlas160 = 0; 32ALLEGRO_BITMAP* avatar_atlas64 = 0; 33ALLEGRO_BITMAP* avatar_atlas32 = 0; 34ALLEGRO_BITMAP* avatar_atlas32bw = 0; 35 36 37 38bool CreateAvatarAtlas(ALLEGRO_BITMAP*& atlas , int w , int h , const char* directory , const char* const type) { 39 40 char avatar_path[4096] = {0}; 41 42 int total_width = NUM_AVATARS*(w+2); 43 int total_height = h + 2; 44 45 if (atlas) { 46 if (!al_is_sub_bitmap(atlas)) { 47 al_destroy_bitmap(atlas); 48 } 49 } 50 51 if (!atlas) { 52 atlas = al_create_bitmap(total_width , total_height); 53 } 54 if (!atlas) { 55 printf("Failed to create %d x %d atlas.\n" , total_width , total_height); 56 return false; 57 } 58 59 60 bool fail = false; 61 62 al_set_target_bitmap(atlas); 63 al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO); 64 al_clear_to_color(al_map_rgba(0,0,0,0)); 65 for (int i = 0 ; i < NUM_AVATARS ; ++i) { 66 sprintf(avatar_path , "%s/%s%s" , directory , avatar_names[i] , type); 67 ALLEGRO_BITMAP* avatar = al_load_bitmap(avatar_path); 68 if (!avatar) { 69 printf("Failed to load avatar %s\n" , avatar_path); 70 fail = true; 71 } 72 else { 73 al_draw_bitmap(avatar , i*(w+2) + 1 , 1 , 0); 74 al_destroy_bitmap(avatar); 75 avatar = 0; 76 } 77 } 78 al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_INVERSE_ALPHA); 79 if (fail) { 80 al_destroy_bitmap(atlas); 81 atlas = 0; 82 } 83 84 return atlas; 85} 86 87 88 89bool CreateAvatars(ALLEGRO_BITMAP* atlas , ALLEGRO_BITMAP** store_sub_avatars , int w , int h) { 90 bool success = true; 91 for (int i = 0 ; i < NUM_AVATARS ; ++i) { 92 success = success && (store_sub_avatars[i] = al_create_sub_bitmap(atlas , i*(w+2) + 1 , 1 , w , h)); 93 } 94 return success; 95} 96 97 98 99bool PopulateAvatars() { 100 bool ret = true; 101 102 ret = ret && CreateAvatarAtlas(avatar_atlas160 , 160 , 160 , "data/avatarpacks/avatarpack160" , "_160x160.png"); 103 ret = ret && CreateAvatarAtlas(avatar_atlas64 , 64 , 64 , "data/avatarpacks/avatarpack64" , "_64x64.png"); 104 ret = ret && CreateAvatarAtlas(avatar_atlas32 , 32 , 32 , "data/avatarpacks/avatarpack32" , "_32x32.png"); 105 ret = ret && CreateAvatarAtlas(avatar_atlas32bw , 32 , 32 , "data/avatarpacks/avatarpack32" , "_32x32bw.png"); 106 107 ret = ret && CreateAvatars(avatar_atlas160 , avatars160 , 160 , 160); 108 ret = ret && CreateAvatars(avatar_atlas64 , avatars64 , 64 , 64); 109 ret = ret && CreateAvatars(avatar_atlas32 , avatars32 , 32 , 32); 110 ret = ret && CreateAvatars(avatar_atlas32bw , avatars32bw , 32 , 32); 111 112 return ret; 113} 114 115 116 117ALLEGRO_BITMAP* GetAvatar(int size , bool bw , int index) { 118 ALLEGRO_BITMAP** avatars = 0; 119 if (size == 160) { 120 avatars = avatars160; 121 } 122 else if (size == 64) { 123 avatars = avatars64; 124 } 125 else if (size == 32) { 126 if (bw) { 127 avatars = avatars32bw; 128 } 129 else { 130 avatars = avatars32; 131 } 132 } 133 else { 134 return 0; 135 } 136 if (index < 0 || index >= NUM_AVATARS) { 137 return 0; 138 } 139 return avatars[index]; 140}

I'm exhausted, so maybe I'm just doing something blatantly wrong. Suggestions welcomed.

Edgar Reynaldo
Member #8,592
May 2007
avatar

The Create* routines set the drawing target. You have to reset it first. Then draw one of the images from GetAvatar. Also, windows is not case sensitive. That's why it didn't care for me, but failed on Linux. Don't know how that sneaky capital K got in there. I'll upload a fixed version tomorrow.

Edit
Here. I just changed the lowercase k to a big K in Avatars.cpp and that should fix it. Just set the drawing target and you're good to go.
https://www.allegro.cc/files/attachment/610691

Eric Johnson
Member #14,841
January 2013
avatar

I'll mess with it some more later on, Edgar.

Merry Krampus, everyone! :D

SiegeLord
Member #7,827
October 2006
avatar

I finished my thing, hopefully before the deadline(s)?!? :o

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

bamccaig
Member #7,536
July 2006
avatar

It seems reasonable that a library like this should restore the original target when its job is done. It seems unlikely that the caller will arbitrarily want to keep drawing to your target.

m c
Member #5,337
December 2004
avatar

I'm volunteering at a 5 day music festival so ill try to finish mine off and upload when i can

{"name":"610693","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/2\/5215e93b9eb5ec2953abacd7b4f12196.jpg","w":800,"h":597,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/2\/5215e93b9eb5ec2953abacd7b4f12196"}610693
{"name":"610694","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/561de3fe4df9b63fb3749c7bd6cb66c2.jpg","w":800,"h":597,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/6\/561de3fe4df9b63fb3749c7bd6cb66c2"}610694
{"name":"610695","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/c\/5c0bef70bac79e1aa77af20ab949c030.jpg","w":800,"h":597,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/c\/5c0bef70bac79e1aa77af20ab949c030"}610695

(\ /)_____#_____####__#
(O.o)¯¯¯#¯¯¯¯¯#¯¯¯#¯¯#
(> <)__####__####__####
Megabytes are where I keep my Data.

amarillion
Member #940
January 2001
avatar

I submitted my thing too, with about 30 hours on the clock from me and about 4 hours from Max.

I roughly got where I wanted, but I got plenty of new ideas. I could easily spend another 30 hours developing the same game for Krampushack 2017 :)

I really like this polish-hack style though... Take an old game, keep it in a releasable state but replace features one by one. I've got so many old competition entries that I could treat the same way. Maybe they have some potential, but really they are just unfinished. Maybe we can make this something regular. What do you think?

--
Martijn van Iersel | My Blog | Sin & Cos | Tegel tilemap editor | TINS 2017

Eric Johnson
Member #14,841
January 2013
avatar

It's a neat idea, but wouldn't work too well for those who haven't made a bunch of games already.

Mark Oates
Member #1,146
March 2001
avatar

I think that's a fantastic idea.

For KrampusHack, I want my game to be more polished than my previous hack games. I always felt my past hacks fell short and ended up closer to engine-and-tech-demo that I would have liked!

Edgar Reynaldo
Member #8,592
May 2007
avatar

bamccaig said:

It seems reasonable that a library like this should restore the original target when its job is done. It seems unlikely that the caller will arbitrarily want to keep drawing to your target.

It's hardly a library. And it doesn't take the display as a parameter, so it can't restore the drawing target to the backbuffer.

It's not hard to do.

There, that wasn't so bad, was it?

Mark Oates
Member #1,146
March 2001
avatar

There, that wasn't so bad, was it?

Yes, actually that is bad. :-/

You shouldn't implicitly change the state, then expect the user to both know what you changed and also have to clean up afterward. I haven't looked at your code, but it sounds like you're changing the drawing target within a function call. Whenever you do that, you should always change it back:

void my_function_that_draws_to_target(ALLEGRO_BITMAP *target)
{
   ALLEGRO_STATE previous_target_bitmap_state;
   al_store_state(&previous_target_bitmap_state, ALLEGRO_STATE_BITMAP);
   al_set_target_bitmap(target);

   // do your drawing here
   // ...

   al_restore_state(&previous_target_bitmap_state);
}

As an (almost holy) principal, any function should have no side effects. If a side effect is essential for the operation of that function, then the side effect should be isolated into a separate function call, and you should make it the responsibility of the user to call it.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Oh grow up. Allegro implicitly changes global state all the time, and it's your responsiblity to set it back. OpenGL much?

Edit
There is one bug in Avatars.cpp on line 47. It should be followed by the following line :

#SelectExpand
45 if (atlas) { 46 if (!al_is_sub_bitmap(atlas)) { 47 al_destroy_bitmap(atlas);
48 atlas = 0;
49 } 50 }

That way it recycles the bitmap properly. It would only come up if you call CreateAtlas twice though.

Derezo
Member #1,666
April 2001
avatar

I feel terrible -- I did not finish at all. I may still try to come up with something before the end of the day tomorrow just to be like "yay happy holidays" :P

"He who controls the stuffing controls the Universe"

Edgar Reynaldo
Member #8,592
May 2007
avatar

Elias
Member #358
May 2000

I'm basically finished, just need to play test and upload... had much less time yesterday and today then I had expected.

--
"Either help out or stop whining" - Evert

Mark Oates
Member #1,146
March 2001
avatar

I still have quite a bit to do, but I've done a ton so far. :) (hmm, odd, it shows 186 commits on the repo. hmmm 🤔)

I'll be glad if I can wrap this up in the next 2 days. :)



Go to: