Turkey haXe game Source Code

April 3rd, 2009 »

full source for Turkey haXe

requested by Raf

crude source code, never thought anyone else would see it after i finished, including myself.

248 lines in the main class. i also created a few supporting classes for this game that i’ve been reusing ever since, and included in my common library.

comments
the haxe compile file

compile.hxml

-swf main.swf
-swf-version 9
-swf-header 550:500:300:FFFFFF
-main TurkeyHaXe

comments
the main class

TurkeyHaXe.hx

import com.remixtechnology.GraphicsLoader;
import flash.Lib;
import flash.display.Stage;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.text.TextField;
import flash.text.TextFormat;

class TurkeyHaXe
{
    public var stage:Stage;
    public var bg_layer:Sprite;
    public var game_layer:Sprite;
    public var over_layer:Sprite;
    private var start_but:Button;
    //private var high_scores_but:Button;
    private var play_again_but:Button;
    private var game_bg:Sprite;
    private var intro_bg:Sprite;
    private var instructions:Sprite;

    private var score:Int;
    private var scoreBoard:ShadowedTextField;
    private var finalScoreBoard:ShadowedTextField;

    private var control:Sprite;
    private var stuffing:Array<Sprite>;
    private var stuffing_graphics:Array<GraphicsLoader>;
    private var fail_graphics:Array<Sprite>;
    private var fail_message:Sprite;
    private var drop_interval:Int; //seconds //current
    private var drop_timer:Timer;
    private var drops:Int;
    private var first_time:Bool;
    private var drop_speed:Float;

    public static function main() {
        new TurkeyHaXe();
    }
    private function new(){
        stage = Lib.current.stage;
        init();
    }
    private function init(){
        //make layers
        bg_layer = new Sprite();
        stage.addChild(bg_layer);
        game_layer = new Sprite();
        stage.addChild(game_layer);
        over_layer = new Sprite();
        stage.addChild(over_layer);

        stuffing = new Array<Sprite>();
        stuffing_graphics = new Array<GraphicsLoader>();
        fail_graphics = new Array<Sprite>();

        score = 0;

        //show start screen
        intro_bg = new GraphicsLoader(Settings.graphics_path + "intro_bg.png").sprite;
        bg_layer.addChild(intro_bg);

        start_but = new Button("intro_start_but.png", "intro_start_but_over_bg.png");
        over_layer.addChild(start_but);
        start_but.addEventListener(MouseEvent.CLICK, click_start_but);
        //start_but.x = 300;
        //start_but.y = 210;
        start_but.x = 200;
        start_but.y = 130;

        /*
        high_scores_but = new Button("intro_high_scores_but.png", "intro_high_scores_but_over_bg.png");
        over_layer.addChild(high_scores_but);
        high_scores_but.x = 260;
        high_scores_but.y = 260;
        start_but.addEventListener(MouseEvent.CLICK, click_high_scores_but); */

        //gimme stuffing
        stuffing_graphics.push(new GraphicsLoader(Settings.graphics_path + "stuffing_0.png"));
        stuffing_graphics.push(new GraphicsLoader(Settings.graphics_path + "stuffing_1.png"));
        stuffing_graphics.push(new GraphicsLoader(Settings.graphics_path + "stuffing_2.png"));

        //gimme fail
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_0.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_1.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_2.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_3.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_4.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_5.png").sprite);
        fail_graphics.push(new GraphicsLoader(Settings.graphics_path + "fail_6.png").sprite);

        first_time = true;
    }
    private function click_start_but(_):Void{
        loadGame();
    }
    private function click_high_scores_but(_):Void{
        //showHighScores();
    }
    private function loadGame():Void{
        drop_interval = Settings.init_drop_interval;
        drop_timer = new Timer(drop_interval);
        drop_timer.addEventListener(TimerEvent.TIMER, tick_drop);
        drop_timer.start();

        drop_speed = Settings.init_drop_speed;

        control = new GraphicsLoader(Settings.graphics_path + "control.png").sprite;
        game_layer.addChild(control);
        control.y = 360;

        stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouse_move);
        stage.addEventListener(Event.ENTER_FRAME, loop);

        if(first_time){ 
            clear_intro();
            game_bg = new GraphicsLoader(Settings.graphics_path + "game_bg.png").sprite;
            bg_layer.addChild(game_bg);
            showInstructions(); 
            scoreBoard = new ShadowedTextField();
            over_layer.addChild(scoreBoard);
            scoreBoard.x = 15;
            scoreBoard.y = 15;
        }
        score = 0;
        scoreBoard.setText(Std.string(score));
        if(Settings.hide_cursor) {Mouse.hide();}
    }
    private function setDropTimer():Void{
        drop_timer.stop();
        drop_timer.removeEventListener(TimerEvent.TIMER, tick_drop);
        drop_timer = null;
        drop_timer = new Timer(drop_interval);
        drop_timer.addEventListener(TimerEvent.TIMER, tick_drop);
        drop_timer.start();
    }
    private function tick_drop(_):Void{
        var randX:Int = Math.round(Math.random()*(stage.stageWidth-80))+30;
        var randS:Int = Math.floor(Math.random()*stuffing_graphics.length);
        var s:Sprite = new Sprite();
        game_layer.addChild(s);
        stuffing_graphics[randS].getCopySprite(s);
        stuffing.push(s);
        s.x = randX;
        s.y = -10;
        s.rotation = Math.round(Math.random()*360);
        drops++;
        if((drops % Settings.increment_drop_speed_every) == 0){
            drop_speed += Settings.increment_drop_speed;
        }
        if( ((drops % Settings.increment_drop_every) == 0) && drop_interval > Settings.min_drop_interval){
            drop_interval -= Settings.increment_drop_interval;
            setDropTimer();
        }
    }
    private function showInstructions():Void{
        var t:Timer = new Timer(3000,1);
        t.addEventListener(TimerEvent.TIMER_COMPLETE, complete_instructions);
        t.start();

        instructions = new GraphicsLoader(Settings.graphics_path + "catch_all_the_stuffing.png").sprite;
        over_layer.addChild(instructions);
        instructions.x = 65;
        instructions.y = 100;

        first_time = false;
    }
    private function complete_instructions(_):Void{
        over_layer.removeChild(instructions);
        instructions = null;
    }
    private function stage_mouse_move(_):Void{
        control.x = stage.mouseX - 40;
    }
    private function loop(_):Void{
        var s:Sprite;
        for(s in stuffing){
            s.y += drop_speed;
            if(s.y >= stage.stageHeight){
                gameOver();
            }else if(s.hitTestPoint(stage.mouseX, 410)){
                stuffing.remove(s);
                game_layer.removeChild(s);
                s = null;
                awardPoints();
            }
        }
    }
    private function clear_intro():Void{
        start_but.parent.removeChild(start_but);
        //high_scores_but.parent.removeChild(high_scores_but);
        intro_bg.parent.removeChild(intro_bg);
        start_but = null;
        //high_scores_but = null;
        intro_bg = null;
    }
    private function awardPoints():Void{
        score += drops + Math.round(drop_speed) + (Settings.init_drop_interval - drop_interval);
        scoreBoard.setText(Std.string(score));
    }
    private function gameOver():Void{
        drop_timer.removeEventListener(TimerEvent.TIMER, tick_drop);
        drop_timer.stop();

        game_layer.removeChild(control);
        control = null;

        var s:Sprite;
        for(s in stuffing){
            game_layer.removeChild(s);
        }

        stuffing = new Array<Sprite>();

        stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouse_move);
        stage.removeEventListener(Event.ENTER_FRAME, loop);

        if(Settings.hide_cursor) {Mouse.show();}

        // show fail message
        var randF:Int = Math.floor(Math.random()*fail_graphics.length);
        fail_message = new Sprite();
        game_layer.addChild(fail_message);
        fail_message.addChild(fail_graphics[randF]);
        fail_message.x = 40;
        fail_message.y = 80;

        // show try again
        play_again_but = new Button("try_again_but.png", "try_again_but_over_bg.png");
        over_layer.addChild(play_again_but);
        play_again_but.x = 150;
        play_again_but.y = 420;
        play_again_but.addEventListener(MouseEvent.CLICK, try_again_click);
    }
    private function try_again_click(_):Void{
        game_layer.removeChild(fail_message);
        fail_message = null;
        play_again_but.removeEventListener(MouseEvent.CLICK, try_again_click);
        over_layer.removeChild(play_again_but);
        play_again_but = null;
        loadGame();
    }

}

comments
a very simple class that loads an external image. i found this class to be very very handy, but is by no means perfect. part of the com.remixtechnology package.

GraphicsLoader.hx

/* loads a graphic (at runtime), returns a Sprite with that graphic in it using getSprite() */
package com.remixtechnology;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
class GraphicsLoader{
    private var fileName:String;
    private var bm:Bitmap;
    private var ldr:Loader;
    private var copies:Array<Sprite>;
    public var sprite:Sprite;
    public var loaded:Bool;
    public function new(_fileName:String){
        fileName = _fileName;
        init();
    }
    private function init():Void{
        loaded = false;
        sprite = new Sprite();
        copies = new Array();
        ldr = new Loader();
        ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete);
        ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loader_ioError);
        ldr.load(new URLRequest(fileName));
    }
    private function loader_ioError(event:IOErrorEvent):Void{
        trace("ioErrorHandler: " + event.text);
        trace("Could not load: " + fileName);
    }
    private function loader_complete(event:Event):Void{
        loaded = true;
        bm = event.target.content;
        sprite.addChild(bm);
        if(copies.length > 0){
            var i:Sprite;
            for(i in copies){
                copySprite(i);
            }
        }
    }
    public function getCopySprite(emptySprite:Sprite):Void{ // gets a copy of the sprite, 
        // but leaves the original alone
        // take an emptySprite, and promise to attach a bitmap when it's done loading
        // track promises using the array 'copies'
        // unless it's already loaded, then just get a copy
        if(loaded){
            copySprite(emptySprite);
        }else{
            copies.push(emptySprite);
        }
    }
    private function copySprite(s:Sprite):Void{
        var data:BitmapData = new BitmapData(Std.int(bm.width), Std.int(bm.height), true, 0);
        data.draw(bm);
        var bitmap:Bitmap = new Bitmap(data);
        s.addChild(bitmap); // promise fulfilled
    }
}

comments
a simple button class that extends Sprite, all it really does is load a couple of graphics to create a rollover state. lines 12 and 13 are little hacks because of the way i exported my graphics. in the newest version of this class, the rollover is a nice fading tween, and of course lines 12 and 13 are not there. and this class has been added to the com.remixtechnology package.

Button.hx

import com.remixtechnology.GraphicsLoader;
import flash.display.Sprite;
import flash.events.MouseEvent;
class Button extends Sprite{
    private var normal_state:Sprite;
    private var over_state:Sprite;
    public function new(normal_state_path:String, over_state_path:String){
        normal_state = new GraphicsLoader(Settings.graphics_path + normal_state_path).sprite;
        over_state = new GraphicsLoader(Settings.graphics_path + over_state_path).sprite;
        addChild(over_state);
        addChild(normal_state);
        normal_state.x = 15;
        normal_state.y = 6;
        over_state.visible = false;
        addListeners();
        super();
    }
    private function addListeners():Void{
        addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
        addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
    }
    private function mouseOver(_):Void{
        over_state.visible = true;
    }
    private function mouseOut(_):Void{
        over_state.visible = false;
    }
}

comments a simple text field class that i use a lot, this version is not very customizable, but i’ve added it to the com.remixtechnology package and made it a lot more customizable with some decent default settings. here i use it to display the score, but i use it a lot for tracing because if you add graphics to the stage, like in this game, it covers haXe’s trace messages.

ShadowedTextField.hx

import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

class ShadowedTextField extends Sprite
{

    private var fgColor:UInt;
    private var bgColor:UInt;
    private var xoff:Float;
    private var yoff:Float;

    private var tfFore:TextField;
    private var tfBack:TextField;
    private var fmtFore:TextFormat;
    private var fmtBack:TextFormat;

    private var size:Int;
    private var font:String;

    public function new()
    {
        bgColor = 0x000000;
        fgColor = Settings.font_color;
        xoff = 1;
        yoff = 1;
        size = 24;
        font = 'Verdana';

        mouseChildren = false;
        mouseEnabled = false;

        tfBack = new TextField();
        tfBack.autoSize = TextFieldAutoSize.LEFT;
        tfBack.selectable = false;
        tfBack.x = xoff;
        tfBack.y = yoff;
        addChild(tfBack);

        tfFore = new TextField();
        tfFore.autoSize = TextFieldAutoSize.LEFT;
        tfFore.selectable = false;
        addChild(tfFore);

        fmtFore = new TextFormat();
        fmtFore.color = fgColor;
        fmtFore.size = size;
        fmtFore.font = font;
        fmtFore.bold = true;

        fmtBack = new TextFormat();
        fmtBack.color = bgColor;
        fmtBack.size = size;
        fmtBack.font = font;
        fmtBack.bold = true;

        super();
    }

    public function setText(n:String):Void
    {
        tfFore.text = n;
        tfFore.setTextFormat(fmtFore);

        tfBack.text = n;
        tfBack.setTextFormat(fmtBack);
    }

}

comments
some settings for the game, not sure why i left it out of the main class, i guess i just wanted a quick way to access some static settings from any class. i think it’s unnecessary, and i don’t do this anymore.

Settings.hx

class Settings{
    public static var hide_cursor:Bool = false;
    //local
    public static var graphics_path:String = "graphics/";
    //on remixtechnology
    //public static var graphics_path:String = "/haXe/turkey_haXe/graphics/";
    public static var init_drop_interval:Int = 1500;
    public static var increment_drop_interval:Int = 50;
    public static var increment_drop_every:Int = 3;
    public static var min_drop_interval:Int = 300;
    public static var init_drop_speed:Float = 4;
    public static var increment_drop_speed:Float = .25;
    public static var increment_drop_speed_every:Float = 5;

    public static var font_color:UInt = 0xffa312;
}

and finally, here is the zip file complete with all assets, everything that i used to create this simple game.

Download the entire source + assets (3.8 Mb)


7 Responses to “Turkey haXe game Source Code”

Say Anything