Drawing arbitrary pixels to FlxSprite



  • This task seems so simple in theory, but I can't seem to find any documentation on the best practice (or any practice, for that matter).

    How do I create a "sketch board," for lack of a better term, on which I can modify pixels individually and have the changes render immediately?

    My first instinct was to write some code like this:

    class PlayState extends FlxState {
        var canvas:FlxSprite;
        var totalTime:Float = 0;
    
        override public function create():Void {
            super.create();
            canvas = new FlxSprite();
            canvas.makeGraphic(128, 128, FlxColor.WHITE, true);
            add(canvas);
        }
    
        override public function update(elapsed:Float):Void {
            super.update(elapsed);
            totalTime += 1;
            canvas.pixels.setPixel(Std.int(totalTime % 128), Std.int(totalTime / 128), 0xFF0000);
        }
    }
    

    ...which I would expect to display a white square that (rapidly!) changes to completely red. But instead, when I run the program, only a single pixel (seems to be (1, 0)) is colored red. The rest of the square is white.

    For context, I am trying to make a Pictionary clone, simply to familiarize myself with HaxeFlixel and go beyond the tilemap dungeon-crawler tutorial on the site. Forgive me for my ignorance.



  • hi @nlrobson

    Maybe stamp() would be a better way to go?
    https://api.haxeflixel.com/flixel/FlxSprite.html#stamp

    You can make a brush. private var _brush = new FlxSprite().makeGraphic(2, 2, 0xFFFF0000);

    canvas.stamp(_brush, Std.int(totalTime % 128), Std.int(totalTime / 128));

    I know it's just to test, but the math you're doing limits the x, y to 0, 0 the first 2 seconds, and 0, 1 until 5 seconds, then 0, 2 after 5 seconds, etc. Std.int() floors it. So it takes over 10 seconds to get to 4 px. Over 1 minute to get to 28 px, so not so rapid, and only the left edge. The modulus % always returns the remainder, so that one is always going to be 0 since Std.int() floors it.



  • stamp() seems to work quite well, in fact! For reference, I modified my code to look like:

    class PlayState extends FlxState {
        var canvas:FlxSprite;
        var totalTime:Int = 0;
    
        override public function create():Void {
            super.create();
            canvas = new FlxSprite();
            canvas.makeGraphic(128, 128, FlxColor.WHITE, true);
            add(canvas);
        }
    
        override public function update(elapsed:Float):Void {
            super.update(elapsed);
            totalTime += 1;
            var brush = new FlxSprite().makeGraphic(2, 2, 0xFFFF0000);
            canvas.stamp(brush, totalTime % 128, Std.int(totalTime / 128));
        }
    }
    

    ...and it behaves as I expected.

    I think that the line totalTime += 1, despite being a terrible naming job on my part, allowed for the red line to cover the square quickly (as opposed to totalTime += elapsed).

    Is stamp() plus a brush an appropriate (efficient) solution even when drawing pixels based on user input, such as with a mouse click/drag or touchscreen? I think that I overlooked that function before because it seemed to be intended for copying entire sprites.

    Thank you so much for your quick and detailed response!


Log in to reply
 

Looks like your connection to HaxeFlixel was lost, please wait while we try to reconnect.