 |
GTK+ Forums Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
|
|
|
| Author |
Message |
|
|
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Wed Feb 17, 2010 2:02 pm Post subject: Need help in developing a simple game - Whack a Mole, GTK |
|
|
Hi avid programmers,
I need help in developing a simple game for my school project.
Im stuck in implementing a timer function to this game.
Can anyone help me? Greatly appreciated!! :)
Below is my code:
--------------------------------------------------------------------------------------------------------
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
| //Program written by: Jimmy Fam
// Updated: 24.01.2010
// Title: Whack a Mole! game
#include <gtk/gtk.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
void increase(GtkWidget *widget, gpointer label)
{
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(label, buf);
}
void decrease(GtkWidget *widget, gpointer label)
{
count--;
sprintf(buf, "%d", count);
gtk_label_set_text(label, buf);
}
void molehit (GtkWidget *widget, gpointer label)
{
sprintf(buf, "Mole hit!! ");
gtk_label_set_text(label, buf);
}
void update (GtkWidget *widget, gpointer label3)
{
//Random number button generator. Number range (0-9)
int finalNum = 1;
finalNum = rand() % (10);
sprintf(buf, "%d", finalNum);
gtk_label_set_text(label3, buf);
}
void wait ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
int main(int argc, char** argv) {
GtkWidget *label;
GtkWidget *window;
GtkWidget *frame;
GtkWidget *plus;
GtkWidget *minus;
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *button3;
GtkWidget *button4;
GtkWidget *button5;
GtkWidget *button6;
GtkWidget *button7;
GtkWidget *button8;
GtkWidget *button9;
GtkWidget *label2;
GtkWidget *label3;
GdkColor colorRed;
GdkColor colorBlue;
GdkColor colorYellow;
GdkColor colorOrange;
GdkColor colorGreen;
gdk_color_parse ("yellow", &colorYellow);
gdk_color_parse ("red", &colorRed);
gdk_color_parse ("blue", &colorBlue);
gdk_color_parse ("orange", &colorOrange);
gdk_color_parse ("green", &colorGreen);
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 300);
gtk_window_set_title(GTK_WINDOW(window), "Whack a Mole");
frame = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), frame);
plus = gtk_button_new_with_label("+");
gtk_widget_set_size_request(plus, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), plus, 110, 20);
minus = gtk_button_new_with_label("-");
gtk_widget_set_size_request(minus, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), minus, 110, 80);
button1 = gtk_button_new_with_label("Mole1");
gtk_widget_set_size_request(button1, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button1, 110, 140);
button2 = gtk_button_new_with_label("Rand");
gtk_widget_set_size_request(button2, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button2, 10, 20);
button3 = gtk_button_new_with_label("Mole3");
gtk_widget_set_size_request(button3, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button3, 10, 80);
button4 = gtk_button_new_with_label("Mole4");
gtk_widget_set_size_request(button4, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button4, 10, 140);
button5 = gtk_button_new_with_label("Mole5");
gtk_widget_set_size_request(button5, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button5, 210, 20);
button6 = gtk_button_new_with_label("Mole6");
gtk_widget_set_size_request(button6, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button6, 210, 80);
button7 = gtk_button_new_with_label("Mole7");
gtk_widget_set_size_request(button7, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), button7, 210, 140);
label = gtk_label_new("0");
gtk_fixed_put(GTK_FIXED(frame), label, 380, 58);
label2 = gtk_label_new("Score");
gtk_fixed_put(GTK_FIXED(frame), label2, 380, 28);
label3 = gtk_label_new("0");
gtk_fixed_put(GTK_FIXED(frame), label3, 380, 88);
gtk_widget_show_all(window);
//C++ game logic starts here..
// 1) 'Main game timer' begins...
// 2) Random number button generator;number range (0-9)...
int finalNum = 1;
finalNum = rand() % (10);
//wait(10);
// 3) Change random button colour to reflect "shown, hit(click) it!"....
if (finalNum = 1)
{ gtk_widget_modify_bg (button1, GTK_STATE_NORMAL, &colorRed); }
if (finalNum = 2)
{ gtk_widget_modify_bg (button2, GTK_STATE_NORMAL, &colorYellow); }
if (finalNum = 3)
{ gtk_widget_modify_bg (button3, GTK_STATE_NORMAL, &colorBlue); }
if (finalNum = 4)
{ gtk_widget_modify_bg (button4, GTK_STATE_NORMAL, &colorGreen); }
if (finalNum = 5)
{ gtk_widget_modify_bg (button5, GTK_STATE_NORMAL, &colorOrange); }
if (finalNum = 6)
{ gtk_widget_modify_bg (button6, GTK_STATE_NORMAL, &colorYellow); }
if (finalNum = 7)
{ gtk_widget_modify_bg (button7, GTK_STATE_NORMAL, &colorYellow); }
if (finalNum = 8)
{ gtk_widget_modify_bg (button8, GTK_STATE_NORMAL, &colorYellow); }
if (finalNum = 9)
{ gtk_widget_modify_bg (button9, GTK_STATE_NORMAL, &colorYellow); }
//return 0;
// 4) 'Mole hit timer'(countdown timer) starts once colour of 1 button changes...
// if mouse click within set time interval, add one point
/* clock: countdown code */
// 5) ELSE exceed 'mole hit timer' before mouse click, minus one point,
/* Minus point for missed hit*/
// G_CALLBACK(decrease), label);
// 6) Reset 'Mole hit timer'(countdown timer)and repeats again until 'Main game counter' finished and display final result "Game Over!".
g_signal_connect(window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect(plus, "clicked",
G_CALLBACK(increase), label);
g_signal_connect(minus, "clicked",
G_CALLBACK(decrease), label);
g_signal_connect(button1, "clicked",
G_CALLBACK(molehit), label);
g_signal_connect(button2, "clicked",
G_CALLBACK(update),label3);
g_signal_connect(button3, "clicked",
G_CALLBACK(molehit), label);
g_signal_connect(button4, "clicked",
G_CALLBACK(molehit), label);
g_signal_connect(button5, "clicked",
G_CALLBACK(molehit), label);
g_signal_connect(button6, "clicked",
G_CALLBACK(molehit), label);
g_signal_connect(button7, "clicked",
G_CALLBACK(molehit), label);
gtk_main();
return 0;
} | Added CodeBB -dreblen |
|
| Back to top |
|
 |
tadeboro Never Seen the Sunlight
Joined: 23 Jul 2008 Posts: 2114 Location: Slovenia
|
Posted: Thu Feb 18, 2010 5:03 pm Post subject: |
|
|
Hello and welcome to the GTK+ forums.
You're having troubles because you use "busy wait loop". Control needs to return to GTK+'s main loop in order for GUI controls to work properly.
If your timing requests are not very strict (couple of ms variance is allowed), you can use g_timeout_add() function to show your "mole". In case of strict timing, you'll probably need to spawn separate thread which will monitor clock and update GUI when appropriate.
Tadej |
|
| Back to top |
|
 |
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Sun Feb 21, 2010 12:29 am Post subject: |
|
|
Thks Tadej,
I revise my code to include a 10sec timer...
My flow is like this,
1) button turns yellow colour, timer start
2) click button before timer stops (10sec) add point, [count ++]
3) if did not click button and timer exceed 10 secs, button turn red.
Can you help me revise my code into this format?? Many thanks!!
Code below:
-----------------------------------------------------------------------------------
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <gtk/gtk.h>
#include <glib.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
gint count = 0;
char buf[5];
gboolean callback (gpointer data) {
int timeout = GPOINTER_TO_INT (data);
printf ("callback called at: %lu\n", time (NULL));
sleep (timeout);
printf ("callback returns at: %lu\n", time (NULL));
g_timeout_add_seconds (20, callback, GINT_TO_POINTER (timeout));
return FALSE;
}
void increase(GtkWidget *widget, gpointer label)
{
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(label, buf);
}
int main (int argc, char **argv) {
GtkWidget *label;
GtkWidget *window;
GtkWidget *frame;
GtkWidget *plus;
GdkColor colorYellow;
gdk_color_parse ("yellow", &colorYellow);
//10 secs timer countdown
int timeout = 10;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 300);
gtk_window_set_title(GTK_WINDOW(window), "Whack a Mole");
frame = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), frame);
plus = gtk_button_new_with_label("+");
gtk_widget_set_size_request(plus, 80, 35);
gtk_fixed_put(GTK_FIXED(frame), plus, 110, 20);
label = gtk_label_new("0");
gtk_fixed_put(GTK_FIXED(frame), label, 380, 58);
gtk_widget_show_all(window);
//10 secs timer countdown
callback (GINT_TO_POINTER (timeout));
gtk_widget_modify_bg (plus, GTK_STATE_NORMAL, &colorYellow);
g_signal_connect(window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect(plus, "clicked",
G_CALLBACK(increase), label);
gtk_main ();
return 0;
} | Added CodeBB -dreblen |
|
| Back to top |
|
 |
tadeboro Never Seen the Sunlight
Joined: 23 Jul 2008 Posts: 2114 Location: Slovenia
|
Posted: Mon Feb 22, 2010 11:58 am Post subject: |
|
|
Hello.
This game intrigued me enough to write a simple whack-a-mole game. But since I don't want to be the one who writes your school projects, I haven't commented my code. Feel free to reuse my code anyway you find suitable, but just make yourself a favor and dissect it until you understand what each part of the code does (apart from some GObject specifics, it's relatively simple code with only cca. 500 lines of code).
You can compile this code like this:
| Code: (Plaintext) | 1 2 3
| gcc -Wall $(pkg-config --cflags gtk+-2.0) -c mymole.c -o mymole.o
gcc -Wall $(pkg-config --cflags gtk+-2.0) -c test_mole.c -o test_mole.o
gcc -Wall -o test_mole test_mole.o mymole.o $(pkg-config --libs gtk+-2.0) |
mymole.h
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #ifndef __MY_MOLE_H__
#define __MY_MOLE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define MY_TYPE_MOLE \
( my_mole_get_type() )
#define MY_MOLE( obj ) \
( G_TYPE_CHECK_INSTANCE_CAST( ( obj ), MY_TYPE_MOLE, MyMole ) )
#define MY_MOLE_CLASS( klass ) \
( G_TYPE_CHECK_CLASS_CAST( ( klass ), MY_TYPE_MOLE, MyMoleClass ) )
#define MY_IS_MOLE( obj ) \
( G_TYPE_CHECK_INSTANCE_TYPE( ( obj ), MY_TYPE_MOLE ) )
#define MY_IS_MOLE_CLASS( klass ) \
( G_TYPE_CHECK_CLASS_TYPE( ( klass ), MY_TYPE_MOLE ) )
#define MY_MOLE_GET_CLASS( obj ) \
( G_TYPE_INSTANCE_GET_CLASS( ( obj ), MY_TYPE_MOLE, MyMoleClass ) )
typedef struct _MyMole MyMole;
typedef struct _MyMoleClass MyMoleClass;
typedef struct _MyMolePrivate MyMolePrivate;
struct _MyMole
{
GtkDrawingArea parent;
/*< Private >*/
MyMolePrivate *priv;
};
struct _MyMoleClass
{
GtkDrawingAreaClass parent_class;
/* Signals */
void (* whacked)( MyMole *mole );
void (* missed) ( MyMole *mole );
};
GType my_mole_get_type ( void ) G_GNUC_CONST;
GtkWidget *my_mole_new ( void );
guint my_mole_get_timeout ( MyMole *mole );
void my_mole_set_timeout ( MyMole *mole,
guint timeout );
gboolean my_mole_get_busy ( MyMole *mole );
void my_mole_activate ( MyMole *mole );
G_END_DECLS
#endif /* __MY_MOLE_H__ */ |
mymole.c
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
| #include "mymole.h"
/* Time (in miliseconds) that state indicator stays shown */
#define STATE_TIMEOUT 1000
/* Signals */
enum
{
WHACKED,
MISSED,
LAST_SIGNAL
};
/* Properties */
enum
{
PROP_0,
PROP_TIMEOUT,
PROP_BUSY
};
/* States */
enum
{
S_NORMAL,
S_UP,
S_WHACKED,
S_MISSED
};
/* Private structure */
#define MY_MOLE_GET_PRIVATE( obj ) \
( G_TYPE_INSTANCE_GET_PRIVATE( ( obj ), MY_TYPE_MOLE, MyMolePrivate ) )
struct _MyMolePrivate
{
gboolean busy;
gint timeout;
gint state;
guint source_id;
};
/* Overriden methods */
static void my_mole_get_property( GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec );
static void my_mole_set_property( GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec );
static gboolean my_mole_button_press( GtkWidget *widget,
GdkEventButton *event );
static gboolean my_mole_expose ( GtkWidget *widget,
GdkEventExpose *event );
/* Private functions */
static gboolean my_mole_timeout_cb ( MyMole *mole );
static gboolean my_mole_clean_state ( MyMole *mole );
static guint mole_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE( MyMole, my_mole, GTK_TYPE_DRAWING_AREA )
static void
my_mole_class_init( MyMoleClass *klass )
{
GParamSpec *pspec;
GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS( klass );
gobject_class->get_property = my_mole_get_property;
gobject_class->set_property = my_mole_set_property;
widget_class->button_press_event = my_mole_button_press;
widget_class->expose_event = my_mole_expose;
/* Properties */
pspec = g_param_spec_uint( "timeout",
"Timeout",
"Amount of time mole is visible",
100, G_MAXUINT, 2000,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS );
g_object_class_install_property( gobject_class, PROP_TIMEOUT, pspec );
pspec = g_param_spec_boolean( "busy",
"Busy",
"Is mole currently busy?",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS );
g_object_class_install_property( gobject_class, PROP_BUSY, pspec );
/* Signals */
mole_signals[WHACKED] =
g_signal_new( "whacked",
G_OBJECT_CLASS_TYPE( klass ),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET( MyMoleClass, whacked ),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0 );
mole_signals[MISSED] =
g_signal_new( "missed",
G_OBJECT_CLASS_TYPE( klass ),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET( MyMoleClass, missed ),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0 );
/* Private data */
g_type_class_add_private( gobject_class, sizeof( MyMolePrivate ) );
}
static void
my_mole_init( MyMole *mole )
{
mole->priv = MY_MOLE_GET_PRIVATE( mole );
/* Default values */
mole->priv->busy = FALSE;
mole->priv->timeout = 2000;
mole->priv->state = S_NORMAL;
mole->priv->source_id = 0;
/* Add events */
gtk_widget_add_events( GTK_WIDGET( mole ), GDK_BUTTON_PRESS_MASK );
}
static void
my_mole_get_property( GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec )
{
MyMolePrivate *priv = MY_MOLE( object )->priv;
switch( prop_id )
{
case PROP_TIMEOUT:
g_value_set_uint( value, priv->timeout );
break;
case PROP_BUSY:
g_value_set_boolean( value, priv->busy ? TRUE : FALSE );
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
break;
}
}
static void
my_mole_set_property( GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec )
{
MyMolePrivate *priv = MY_MOLE( object )->priv;
switch( prop_id )
{
case PROP_TIMEOUT:
priv->timeout = g_value_get_uint( value );
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
break;
}
}
static gboolean
my_mole_expose( GtkWidget *widget,
GdkEventExpose *event )
{
gboolean r_val = TRUE;
cairo_t *cr;
cr = gdk_cairo_create( event->window );
switch( MY_MOLE( widget )->priv->state )
{
case S_NORMAL:
r_val = FALSE;
break;
case S_UP:
cairo_set_source_rgb( cr, 0, 0, 1 );
cairo_paint( cr );
break;
case S_WHACKED:
cairo_set_source_rgb( cr, 0, 1, 0 );
cairo_paint( cr );
break;
case S_MISSED:
cairo_set_source_rgb( cr, 1, 0, 0 );
cairo_paint( cr );
break;
}
cairo_destroy( cr );
return( r_val );
}
static gboolean
my_mole_button_press( GtkWidget *widget,
GdkEventButton *event )
{
MyMolePrivate *priv = MY_MOLE( widget )->priv;
if( priv->state == S_UP )
{
g_source_remove( priv->source_id );
g_signal_emit( widget, mole_signals[WHACKED], 0 );
priv->state = S_WHACKED;
gtk_widget_queue_draw( widget );
gdk_threads_add_timeout( STATE_TIMEOUT,
(GSourceFunc)my_mole_clean_state,
MY_MOLE( widget ) );
}
return( TRUE );
}
/* Private functions */
static gboolean
my_mole_timeout_cb( MyMole *mole )
{
MyMolePrivate *priv = mole->priv;
priv->source_id = 0;
priv->state = S_MISSED;
gtk_widget_queue_draw( GTK_WIDGET( mole ) );
g_signal_emit( mole, mole_signals[MISSED], 0 );
gdk_threads_add_timeout( STATE_TIMEOUT,
(GSourceFunc)my_mole_clean_state,
mole );
return( FALSE );
}
static gboolean
my_mole_clean_state( MyMole *mole )
{
MyMolePrivate *priv = mole->priv;
priv->state = S_NORMAL;
priv->busy = FALSE;
gtk_widget_queue_draw( GTK_WIDGET( mole ) );
return( FALSE );
}
/* Public API */
GtkWidget *
my_mole_new( void )
{
return( g_object_new( MY_TYPE_MOLE, NULL ) );
}
guint
my_mole_get_timeout( MyMole *mole )
{
g_return_val_if_fail( MY_IS_MOLE( mole ), 0 );
return( mole->priv->timeout );
}
void
my_mole_set_timeout( MyMole *mole,
guint timeout )
{
g_return_if_fail( MY_IS_MOLE( mole ) );
mole->priv->timeout = timeout;
}
gboolean
my_mole_get_busy( MyMole *mole )
{
g_return_val_if_fail( MY_IS_MOLE( mole ), FALSE );
return( mole->priv->busy );
}
void
my_mole_activate( MyMole *mole )
{
MyMolePrivate *priv;
g_return_if_fail( MY_IS_MOLE( mole ) );
priv = mole->priv;
g_return_if_fail( ! priv->busy );
priv->busy = TRUE;
priv->state = S_UP;
gtk_widget_queue_draw( GTK_WIDGET( mole ) );
priv->source_id = gdk_threads_add_timeout( priv->timeout,
(GSourceFunc)my_mole_timeout_cb,
mole );
} |
test_mole.c
| Code: (C) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include "mymole.h"
#define NO_MOLES 2
typedef struct _Data
{
MyMole *moles[9]; /* All moles */
GtkLabel *l_hits, /* Hits label */
*l_miss; /* Miss label */
GtkWidget *button; /* Start game button */
gint hits, /* Hits counter */
miss; /* Miss counter */
}
Data;
static gboolean
show_mole( Data *data )
{
gint val;
/* Loop that ensures we don't re-activate already active mole */
do
{
val = g_random_int_range( 0, 9 );
}
while( my_mole_get_busy( data->moles[val] ) );
my_mole_activate( data->moles[val] );
return( FALSE );
}
static void
cb_clicked( GtkButton *button,
Data *data )
{
gint i;
gint timeout = 1000;
gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
for( i = 0; i < NO_MOLES; i++, timeout += 700 )
{
g_timeout_add( timeout, (GSourceFunc)show_mole, data );
}
}
static void
cb_whacked( MyMole *mole,
Data *data )
{
gchar *text;
text = g_strdup_printf( "Hits: %d", ++data->hits );
gtk_label_set_label( data->l_hits, text );
g_free( text );
g_timeout_add( 1300, (GSourceFunc)show_mole, data );
}
static void
cb_missed( MyMole *mole,
Data *data )
{
gchar *text;
text = g_strdup_printf( "Misses: %d", ++data->miss );
gtk_label_set_label( data->l_miss, text );
g_free( text );
g_timeout_add( 1000, (GSourceFunc)show_mole, data );
}
int
main( int argc,
char **argv )
{
GtkWidget *window,
*vbox,
*table,
*mole,
*hbox,
*button,
*label;
gint i,
j;
Data *data;
gtk_init( &argc, &argv );
data = g_slice_new0( Data );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
g_signal_connect( G_OBJECT( window ), "destroy",
G_CALLBACK( gtk_main_quit ), NULL );
vbox = gtk_vbox_new( FALSE, 5 );
gtk_container_add( GTK_CONTAINER( window ), vbox );
table = gtk_table_new( 3, 3, TRUE );
gtk_box_pack_start( GTK_BOX( vbox ), table, TRUE, TRUE, 0 );
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
mole = my_mole_new();
g_signal_connect( G_OBJECT( mole ), "whacked",
G_CALLBACK( cb_whacked ), data );
g_signal_connect( G_OBJECT( mole ), "missed",
G_CALLBACK( cb_missed ), data );
gtk_widget_set_size_request( mole, 50, 50 );
gtk_table_attach_defaults( GTK_TABLE( table ), mole,
j, j + 1, i, i + 1 );
data->moles[i * 3 + j] = MY_MOLE( mole );
}
}
hbox = gtk_hbox_new( FALSE, 5 );
gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, FALSE, 0 );
button = gtk_button_new_with_label( "Start game" );
g_signal_connect( G_OBJECT( button ), "clicked",
G_CALLBACK( cb_clicked ), data );
gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
data->button = button;
label = gtk_label_new( "Hits: 0" );
gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
data->l_hits = GTK_LABEL( label );
label = gtk_label_new( "Misses: 0" );
gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
data->l_miss = GTK_LABEL( label );
gtk_widget_show_all( window );
gtk_main();
g_slice_free( Data, data );
return( 0 );
} |
Tadej |
|
| Back to top |
|
 |
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Wed Feb 24, 2010 4:03 pm Post subject: |
|
|
Hi Tadej,
Wow, thanks for helping out in a sample code.
Deeply appreciate!
Complied this code and it works!
I will study this code closely.. and further modified it to make it more fun.
Will try to replace colors with picture animation if possible.
Will update soon in this thread
Thanks again!
Regards,
Jimmy |
|
| Back to top |
|
 |
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Tue Mar 09, 2010 9:29 am Post subject: |
|
|
Hi Tadej,
I cant figure out how to show pictures for clicking.
I understand your program uses Cairo to draw the colored squares. Can you help me out?
Thanks!!
Jimmy |
|
| Back to top |
|
 |
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Wed Mar 10, 2010 12:27 am Post subject: |
|
|
I have written the program flow below:
Whack A Mole!
To begin, Click on Game Icon, Program excutes and load user "Game diffculty selection screen"
User have to chose between 3 difficulty levels. "Easy, Normal, Hard".
When User selects "Easy" mode. The game begins with 9 holes. 1 mole will pop out randomly from the the holes for the user to click within the time interval of 4 secs. Success hit will display a pic of a Mole been hit. A Miss hit will display a pic of a Mole smiling and a Miss word on top of its head.
When User selects "Normal" mode. The game begins with 16 holes. 3 moles will pop out randomly from the the holes for the user to click within the timeinterval of 2 secs. Success hit will display a pic of a Mole been hit. A Miss hit will display a pic of a Mole smiling and a Miss word on top of its head.
When User selects "Hard" mode. The game begins with 25 holes. 5 mole will pop out randomly from the the holes for the user to click within the interval of 2 secs. Success hit will display a pic of a Mole been hit. A Miss hit will display a pic of a Mole smiling and a Miss word on top of its head.
All 3 levels have a master timer of 30 secs. When timer ends, Screen display the full score earned, the number of hits and misses. Game recycle back to "Game diffculty selection screen" upon clicking ok. The game can be played again. |
|
| Back to top |
|
 |
jimmyfam Familiar Face
Joined: 17 Feb 2010 Posts: 17
|
Posted: Fri Apr 02, 2010 7:28 am Post subject: |
|
|
Hi Tadej,
I have studied & used your code to develop it further. You can see my code as posted below.
I encounter some problems, on line 220 of test_mole.c, is it possible to create the tables only after i select one of the radio buttons(Game Diffculty) in page 2?
I want to have the ability to select and set a 4 x 4, 5 x 5 squares, instead of the 3 x 3 squares as default in your sample program.
test_mole.c
| Code: (Plaintext) | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
| #include <gtk/gtk.h>
#include <string.h>
#include "mymole.h"
#include <gdk/gdkkeysyms.h>
//Declarations
gint moleint;
gint tableint;
gint holesint;
//MyMole *moles[9];
GtkLabel *l_hits, *l_miss;
GtkWidget *button;
gint hits,miss;
//Game Defaults (Easy mode)
moleint = 2;
tableint = 3;
holesint = 9;
//No codes before this line
typedef struct _Data
{
//MyMole *moles[holesint];
MyMole *moles[9]; /* All moles */
}
Data;
static void button_clicked (GtkButton*, GtkAssistant*);
static void assistant_cancel (GtkAssistant*, gpointer);
static void assistant_close (GtkAssistant*, gpointer);
static void cb_toggled (GtkToggleButton*, GtkAssistant*);
typedef struct
{
GtkWidget *widget;
gint index;
const gchar *title;
GtkAssistantPageType type;
gboolean complete;
} PageInfo;
//Cairo graphics declaration
cairo_surface_t *surface1;
cairo_surface_t *surface2;
cairo_surface_t *surface3;
cairo_surface_t *surface4;
static void create_surfaces() {
//Insert and edit images here
//NOT UP
surface4 = cairo_image_surface_create_from_png("mole hole.png");
//UP
surface1 = cairo_image_surface_create_from_png("mole up.png");
//WHACKED
surface2 = cairo_image_surface_create_from_png("mole hit.png");
//MISSED
surface3 = cairo_image_surface_create_from_png("mole smile2.png");
}
static void destroy_surfaces() {
g_print("destroying surfaces");
cairo_surface_destroy(surface1);
}
static gboolean
show_mole( Data *data )
{
gint val;
//Loop that ensures we don't re-activate already active mole
do
{
val = g_random_int_range( 0, 9);
g_print("val = %d pressed\n",val);
g_print("moleint = %d \n",moleint);
g_print("tableint = %d \n",tableint);
g_print("holesint = %d \n",holesint);
}
while( my_mole_get_busy( data->moles[val] ) );
my_mole_activate( data->moles[val] );
return( FALSE );
}
static void
cb_clicked( GtkButton *button,
Data *data )
{
gint i;
gint timeout = 1000;
gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
for( i = 0; i < moleint; i++, timeout += 700 ) //0.7sec
//for( i = 0; i < NO_MOLES; i++, timeout += 700 )
{
g_timeout_add( timeout, (GSourceFunc)show_mole, data );
}
}
static void
cb_whacked( MyMole *mole,
Data *data )
{
gchar *text;
text = g_strdup_printf( "Hits: %d", ++hits);
gtk_label_set_label( l_hits, text );
g_free( text );
g_timeout_add( 1300, (GSourceFunc)show_mole, data );
}
static void
cb_missed( MyMole *mole,
Data *data )
{
gchar *text;
text = g_strdup_printf( "Misses: %d", ++miss );
gtk_label_set_label( l_miss, text );
g_free( text );
g_timeout_add( 1000, (GSourceFunc)show_mole, data );
}
int main (int argc,
char *argv[])
{
GtkWidget *assistant, *radio1,*radio2,*radio3,*hbox, *vbox, *label;
GtkWidget *table,
*mole;
gint i,
j;
// Data *data;
//gint i;
//gchar label[] = "Radio ";
//guint i;
PageInfo page[5] = {
{ NULL, -1, "Introduction", GTK_ASSISTANT_PAGE_INTRO, TRUE},
{ NULL, -1, "Diffculty Selection page", GTK_ASSISTANT_PAGE_CONTENT, FALSE},
{ NULL, -1, "Game Start", GTK_ASSISTANT_PAGE_CONTENT, FALSE},
{ NULL, -1, "Click the Button", GTK_ASSISTANT_PAGE_PROGRESS, FALSE},
{ NULL, -1, "Confirmation", GTK_ASSISTANT_PAGE_CONFIRM, TRUE},
};
gtk_init (&argc, &argv);
Data *data = g_slice_new0( Data );
hits = 0;
miss = 0;
/* Create a new assistant widget with no pages. */
assistant = gtk_assistant_new ();
gtk_widget_set_size_request (assistant, 450, 300);
gtk_window_set_title (GTK_WINDOW (assistant), "Whack a Mole");
g_signal_connect (G_OBJECT (assistant), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
page[0].widget = gtk_label_new ("This is an example of a Whack a Mole. By\n"\
"clicking the forward button, you can continue\n"\
"to the next section!");
page[1].widget = gtk_vbox_new(FALSE, 5);
page[2].widget = table = gtk_vbox_new(FALSE, 5);
page[3].widget = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
page[4].widget = gtk_label_new ("Text has been entered in the label and the\n"\
"combo box is clicked. If you are done, then\n"\
"it is time to leave!");
//Game Diffculty Selection page
/* Create three radio buttons where the second two join radio1's group. */
radio1 = gtk_radio_button_new_with_label (NULL, "Easy");
radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
"Normal!");
radio3 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio2),
"Hard");
/* Create the necessary widgets for the second page. */
vbox = gtk_vbox_new(FALSE, 5);
g_signal_connect( radio1, "toggled", G_CALLBACK( cb_toggled ), (gpointer) assistant );
g_object_set_data( G_OBJECT( radio1 ), "id", 1);
g_signal_connect( radio2, "toggled", G_CALLBACK( cb_toggled ), (gpointer) assistant );
g_object_set_data( G_OBJECT( radio2 ), "id", 2);
g_signal_connect( radio3, "toggled", G_CALLBACK( cb_toggled ), (gpointer) assistant );
g_object_set_data( G_OBJECT( radio3 ), "id", 3);
gtk_box_pack_start (GTK_BOX (page[1].widget), radio1, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (page[1].widget), radio2, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (page[1].widget), radio3, FALSE, FALSE, 5);
//Begin 3rd page
//Draw table, must select diffculty option before this step
//Added
create_surfaces();
vbox = gtk_vbox_new( FALSE, 5 );
//gtk_container_add( GTK_CONTAINER(assistant), vbox );
//Must update tableint here....how??
g_print("Printing table now!!!!");
table = gtk_table_new( tableint, tableint, TRUE );
gtk_box_pack_start( GTK_BOX( page[2].widget ), table, TRUE, TRUE, 0 );
for( i = 0; i < tableint; i++ )
{
for( j = 0; j < tableint; j++ )
{
mole = my_mole_new();
g_signal_connect( G_OBJECT( mole ), "whacked",
G_CALLBACK( cb_whacked ), data);
g_signal_connect( G_OBJECT( mole ), "missed",
G_CALLBACK( cb_missed ), data);
gtk_widget_set_size_request( mole, 50, 50 );
gtk_table_attach_defaults( GTK_TABLE( table ), mole,
j, j + 1, i, i + 1 );
//Must be 3 if not error!
data->moles[i * tableint + j] = MY_MOLE( mole );
}
}
hbox = gtk_hbox_new( FALSE, 5 );
gtk_box_pack_start( GTK_BOX(page[2].widget), hbox, FALSE, FALSE, 0 );
button = gtk_button_new_with_label( "Start game" );
g_signal_connect( G_OBJECT(button), "clicked",
G_CALLBACK( cb_clicked ), data);
gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
button = button;
label = gtk_label_new( "Hits: 0" );
gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
l_hits = GTK_LABEL( label );
label = gtk_label_new( "Misses: 0" );
gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
l_miss = GTK_LABEL( label );
/* Add five pages to the GtkAssistant dialog. */
for (i = 0; i < 5; i++)
{
page[i].index = gtk_assistant_append_page (GTK_ASSISTANT (assistant),
page[i].widget);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant),
page[i].widget, page[i].title);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant),
page[i].widget, page[i].type);
/* Set the introduction and conclusion pages as complete so they can be
* incremented or closed. */
gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant),
page[i].widget, page[i].complete);
}
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (button_clicked), (gpointer) assistant);
g_signal_connect (G_OBJECT (assistant), "cancel",
G_CALLBACK (assistant_cancel), NULL);
g_signal_connect (G_OBJECT (assistant), "close",
G_CALLBACK (assistant_close), NULL);
gtk_widget_show_all (assistant);
gtk_main ();
destroy_surfaces();
return 0;
}
static void
button_clicked (GtkButton *button,
GtkAssistant *assistant)
{
GtkWidget *page;
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
page = gtk_assistant_get_nth_page (assistant, 3);
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
/* If the dialog is cancelled, delete it from memory and then clean up after
* the Assistant structure. */
static void
assistant_cancel (GtkAssistant *assistant,
gpointer data)
{
gtk_widget_destroy (GTK_WIDGET (assistant));
}
/* This function is where you would apply the changes and destroy the assistant. */
static void
assistant_close (GtkAssistant *assistant,
gpointer data)
{
g_print ("You would apply your changes now!\n");
gtk_widget_destroy (GTK_WIDGET (assistant));
}
//Functions
void
cb_toggled( GtkToggleButton *radio1,
GtkAssistant *assistant)
{
int button_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(radio1),"id"));
if( gtk_toggle_button_get_active( radio1 ) )
g_print("\nRadio %d pressed\n",button_id);
switch(button_id){
case 1:
moleint = 2;
tableint = 3;
holesint = 9;
//g_print("\nEasy mode selected!");
break;
case 2:
moleint = 3;
tableint = 4;
holesint = 16;
//g_print("\nNormal mode selected!");
break;
case 3:
moleint = 5;
tableint = 5;
holesint = 25;
//g_print("\nHard mode selected!");
};
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
| |
|
| Back to top |
|
 |
|
Powered by phpBB © 2001, 2005 phpBB Group CodeBB 1.0 Beta 2
|