Search the Community

Showing results for tags 'children'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • HTML5 Game Coding
    • News
    • Game Showcase
    • Coding and Game Design
  • Frameworks
    • Phaser
    • Pixi.js
    • Babylon.js
    • Panda.js
    • melonJS
    • Haxe JS
    • Kiwi.js
  • General
    • General Talk
  • Business
    • Collaborations (un-paid)
    • Jobs (Hiring and Freelance)
    • Services Offered

Found 26 results

  1. Hi, Don't know if this is intended behavior but ActionManager executes actions on disabled meshes too. Don't want it run on disabled meshes. Also actions registered with a parent mesh are not executed by children. Got children to execute parent action by registering action to each end child. For meshes disposed/created actionManager to toggle action execution when they are disabled/enabled. So found a way around both, if anyone is looking for it. If there is a better way, please tell. Would love to see ActionManager handle this internally. Thankyou And yeah pg:
  2. Hello all I am pretty new to Phaser. Now I am testing to create drag and drop shape game. I use this code : var background = game.add.sprite(0, 0, 'atlas', 'background.png'); var shape = game.add.sprite(0, 0, 'atlas_test'); shape.frameName = 'ellipse.png' ; shape.inputEnabled = true; shape.input.enableDrag(); In short, this works fine, I drag with my mouse, and it follows my mouse pointer location. But problem happens when I add this : background.addChild(shape); When I add the draggable shape into background, somehow the draggable shape is several x and y away from the actual mouse pointer. Like, the shape is 'late'. I wonder if the shape is following the background viewport since background is the parent. Initially, my pointer on the center of this ellipse, then I drag to northeast, the shape follows the pointer but kind of late. I wonder if is there any lead I can look upon, I need to persist shape as child of background, with normal drag as if the shape is not a of anyone's children. Thank you.
  3. tl;dr when I move parent, child position is updated too late, how to manually force to update child position when I move parent? Hello, in my game I have a group of sprite objects (Ships) this.shipsGroup =; Each Ship before adding to this.shipsGroup have two other groups as children : var actualShip =; var surrounding =; for (var m = 0; m < 3; m++) { var temp = game.add.sprite(-halfSize - 50 + l*50, tempy, 'red'); temp.anchor.setTo(0,1); tempy+=50; if(m == 1 && l > 0 && l < ship.unitSize+1) { actualShip.add(temp); } else { surrounding.add(temp); } } ship.addChild(actualShip); ship.addChild(surrounding); this.shipsGroup.add(ship); Note: every child object has position relative to parent (so child position (0,0) is on parent) Everything is fine up to this point. I'm moving my ships using something like that in every possible direction (I'm moving them on 50x50grid). This check is in update method of game. if(this.draggedShip.position.x - game.input.mousePointer.x >= 50 && some_boundary_condition) { this.draggedShip.position.x-=50; this.checkOverlap(); } So, after my ship has moved to next grid, I'm calling checkOverlap function to check on top of which grid fields actually is the ship. (I have seperate group of sprites for each grid field) checkOverlap: function() { for (var i = 0; i < this.draggedShip.children[0].length; i++) { for(var j = 0; j < this.fieldsGroup.children.length; j++) { if(this.draggedShip.children[0].children[i].overlap(this.fieldsGroup.children[j])) { this.fieldsGroup.children[j].alpha = 1; } } } }, What is wrong : it looks like sprite.overlap uses OLD children positions (before parent move). So when I move my ship 1 field to the left, the result of this checkOverlap function are fields where the ship was in previous step. How it should be: children positions should be updated before my checkOverlap call. How can I force to do it? I was trying to call update on childrens but it didn't work. Phaser 2.6.2
  4. Hi guys, I was trying to make a group of objects and got the following error: phaser.js:45776 Uncaught TypeError: Cannot read property 'length' of undefined Everything seems to be fine, anyone has a clue why this might be happening? FYI: I'm using Phaser 2.5.0 Thank you for your help.
  5. When transform is added to parent, it's also added to children right? In some case I don't want this - I want to control my self, how children reacts when parent transform is changed. Can I do that? Any advice?
  6. Hi i need some help with my school assignment so what i want to do is to kill the children at the same time if all the children's y position more than 820. or if i can check all the position of the children or the group ( i dont think that possible). animals.forEach(function(animal) { var z=0; if (animal.y > 820) { z++; console.log(z); } if (z>6) {animal.kill();} } ); the number of the children is 5 and the problem is the number of z is always 1 therefor the animal.kill() never been process. thought?? or do you have better way to check the position? really appreciate the help guys thanks
  7. Hello, this is my first time developing a game, ever. So please bear with me Currently I'm making a game where a player can shoot bullets at enemies. Each enemy has it's own healthbar, which should decrease when a bullet hits the enemy. For now, implemented the healthbars as a spritesheet with 5 different frames and added them as children to the enemies. function create() { enemies =; game.physics.arcade.enable(enemies); enemies.physicsBodyType = Phaser.Physics.ARCADE; enemies.enableBody = true; bars =; for (var i = 0; i < 5; i++) { enemy[i] = enemies.create(base1.body.x + game.rnd.integerInRange(0, 150), game.rnd.integerInRange(0, 150), 'enemy'); enemy[i].anchor.set(0.5); enemy[i].health = 100; bar = bars.create(0, -30, 'bar'); //sticking the healthbar to the enemy enemy[i].addChild(bar); bar.anchor.setTo(0.5); bar.frame = 0; // first frame -> full healthbar } } function update() { game.physics.arcade.overlap(bullets, enemies, bulletHitsEnemy, null, this); } function bulletHitsEnemy(bullet, enemy) { bar.frame += 1; // decreasing the healthbar bullet.kill(); -= 20; if ( <= 0) { enemy.kill(); } } The problem is that when I hit one of the enemies, only the healthbar of the first spawned enemy changes, all the other ones stay the same. I guess it's a problem with the bulletHitsEnemy() function, because it seems that bar.frame += 1 refers to the very first healthbar created in the enemy creation loop. Any ideas how to fix this? Thanks.
  8. I have an invisible mesh that is the parent of a few child boxes, ordered horizontally one near the other. I'm using the following line to figure out the size of a mesh: getBoundingInfo().boundingBox.extendSize.scale(2) When called on each of the child boxes, the vector returned is correct. When called on the parent mesh, (0, 0, 0) is returned. Is there a way to get the size of the parent, taking into account all of its children?
  9. Is there a way to set the visibility of a mesh to false and have all of it's child meshes be affected as well? I'm setting the children using .parent = parentMesh. Currently it seems that the only way is to loop through all of the children manually. The major problem with this approach is when you have children of children of children. Here is a PG to demonstrate. Uncomment the comment block. var materialSphere = new BABYLON.StandardMaterial("texture2", scene); materialSphere.diffuseColor = new BABYLON.Color3(1, 0, 0); //Red materialSphere.alpha = 0.2; // grand parent var grandParent = BABYLON.Mesh.CreateSphere("sphere1", 16, 3, scene); grandParent.material = materialSphere; // parent var parent = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene); parent.material = materialSphere; parent.parent = grandParent; // child var child = BABYLON.Mesh.CreateSphere("sphere1", 16, 1, scene); child.material = materialSphere; child.parent = parent; // uncomment block below to hide the grandParent and its children /* grandParent.visibility = false; // grandParent.getChildren().forEach(function(_child) { _child.visibility = false; }, this); */ // although children's children are not effected
  10. Hi all, I build simple word match game: If you play game you can see that elements not always disappear, for some reason after selected element removed and other moved down his children element disappear: and must be: It happends after letter moves. Bug step by step: Step 1: Step 2 (all good): Step 3 ( repeat step 2): Result step 3 ( FAIL ): I dont't understand where i made mistake. Fanks for attention: Source code: Source code ( board.ts ): ///<reference path="../def/require.d.ts"/> ///<reference path="../def/lodash.d.ts"/> ///<reference path="../game.ts"/> ///<reference path="../boot.ts"/> define(['phaser', 'lodash'],function(Phaser, _) { class Board { game: any; letters: any; tileWidth: number; tileHeight: number; userSelect: any = []; word: string = ''; btnExit: any; btnHelp: any; btnSound: any; btnMusic: any; btnCoin: any; movesCounter: any; userCoin: number = 250; userScore: any; coinCountLabel: any; levelTheme: any; hoverSound: any; tileMoveSound: any; letterGrid: any = [ [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null], ]; constructor(game: any) { = game; this.tileWidth ='field').width; this.tileHeight ='field').height; this.tileMoveSound ='tile_move'); this.hoverSound ='tile_select'); // Саундтрек игровой комнаты this.levelTheme ='level_theme', 1, true).play(); // Создаем кнопку выхода и назначаем обработчик this.btnExit =, - 80, 'btn_exit', this.exit, this, 1, 0, 2, 0); this.btnExit.input.useHandCursor = true; this.btnExit.onOverSound = this.hoverSound; // Создаем кнопку подсказки и назначаем обработчик this.btnHelp = - 81, - 80, 'btn_help',, this, 1, 0, 2, 0); this.btnHelp.input.useHandCursor = true; this.btnHelp.onOverSound = this.hoverSound; // Создаем кнопку вкл/вкл звуков и назначаем обработчик this.btnSound =, - 45, 'btn_sound', this.toggleSound, this, 1, 0, 2, 0); this.btnSound.input.useHandCursor = true; this.btnSound.onOverSound = this.hoverSound; // Создаем кнопку вкл/вкл музыки и назначаем обработчик this.btnMusic =, - 45, 'btn_music', this.toggleMusic, this, 1, 0, 2, 0); this.btnMusic.input.useHandCursor = true; this.btnMusic.onOverSound = this.hoverSound; // Индикатор монет this.btnCoin = - 164, -5, 'btn_coin', this.buyCoin, this, 1, 0, 2, 0); this.btnCoin.input.useHandCursor = true; this.btnCoin.onOverSound = this.hoverSound; this.coinCountLabel =, 23, this.userCoin, {font: "bold 32px Arial", fill: "#EEFF9C"}); this.btnCoin.addChild(this.coinCountLabel); } toggleSound() { this.hoverSound.mute = this.hoverSound.mute ? false : true; this.tileMoveSound.mute = this.tileMoveSound.mute ? false : true; } toggleMusic() { this.levelTheme.mute = this.levelTheme.mute ? false : true; } buyCoin() { alert('покупка монет'); } /** Заполняем доску буквами - на данный момент не испльзуется */ initTiles() { let self = this; for (let i = 0; i < self.letterGrid.length; i++) { for (let j = 0; j < self.letterGrid.length; j++) { let tile = self.addLetterTile(i, j); self.letterGrid[i][j] = tile; } } } addLetterTile(x: number, y: number) {} resetTile() { // Проходим циклом по каждой колонке начиная слева for(let i = 0; i < this.letterGrid.length; i++) { // Проходим циклом по каждой букве снизу вверх for(let j = this.letterGrid[i].length - 1; j > 0; j--) { // Если область пустая, но область выше нет, смещаем на одну вниз if(this.letterGrid[i][j] === null && this.letterGrid[i][j-1] !== null) { let tempTile = this.letterGrid[i][j-1]; // Меняем буквы местами this.letterGrid[i][j] = tempTile; this.letterGrid[i][j-1] = null; // Добавим анимацию перемещения this.moveDown(tempTile, j); // Перемещаем указатель снова вверх для повторного прохода массива // Примечание: мы не указываем this.letterGrid[i].length - 1 так как данное значение уже будет изменено // В данный момент мы в конце цикла // Данная процедура будет повторятся до тех пор пока в данном массиве все null значения // небудут перемещенны вверх j = this.letterGrid[i].length; } } } // Звук падения камней; } exit() { alert('You leave the room'); } help() { alert('Подсказка'); } moveDown(letter: any, position: number) { let tw =;{y: (LETTER_SIZE_SPACED * position) + (LETTER_SIZE_SPACED / 2) + 150}, 600, Phaser.Easing.Bounce.Out, true); } fillTile() {} // Deprecated fill() { let letterIndex: number = 0, letterContainer: any, letter: any, ground: any, time: any = new Date(); // Создаем группу которая будет содержать буквы this.letters =; this.letters.enableBody = true; for(let i = 0; i < BOARD_COLS; i++) { // Заполняем массив буквами for (let j = 0; j < BOARD_ROWS; j++) { letterIndex = Math.floor(Math.random() * (31 - 0)); letterContainer = this.letters.create( i * LETTER_SIZE_SPACED + (LETTER_SIZE_SPACED / 2) + 200, j * LETTER_SIZE_SPACED + (LETTER_SIZE_SPACED / 2) + 150, 'field' ); // Устанавливаем точку объекту по центру // для выравнивания текста и анимации letterContainer.anchor.setTo(0.5, 0.5); // Устанавливаем стартовый размер в 0 letterContainer.scale = { type: 25, x: 0.4, y: 0.4 }; letter = 0, 0, ALPHABET[letterIndex], { font: "bold 38px Arial", fill: "#5E1400", // Выравние текста по центру boundsAlignH: "center", boundsAlignV: "middle" }); // Генерируем уникальный id для каждой буквы letter.uid = (Math.random() * time.getTime()).toFixed(); // Обработка событий мышки на буквах letter.inputEnabled = true;, this);, this); // Запоминаем позицию буквы на карте letterContainer.gridPosition = { y: i, x: j }; // Устанавливаем границы контейнера буквы letter.setTextBounds(0, 0, 0, 0); // Помещаем букву в контейнер с фоном letterContainer.addChild(letter); // fill board letterGrid this.letterGrid[i][j] = letterContainer; // Анимация появления буквы{x: 1, y: 1}, 700, Phaser.Easing.Bounce.Out, true); } } } /** * Change letter state * * @param {obect} letter - obect contain leter * @param {letter} state - letter state ( normal, selected, active) */ changeLetterState(letter: any, state: string) { let tw: any; switch(state) { case 'select': // Меняем цвет и фон буквы letter.parent.loadTexture('field_active'); letter.fill = '#ffffff'; // Заносим букву в список выделенных и запускаем анимацию нажатия // tw ={x: 0.2, y: 0.2}, 400, Phaser.Easing.Bounce.Out, true); this.word += letter.text; break; default: break; } } /** * Устанавливаем флаг нажатия когда пользователь кликнул по тайлу * * @public * @param {obect} - contain letter obect */ selectLetter(letter: any) {; // Заносим букву в выбранные this.userSelect.push(letter.parent); // Меняем состояние буквы this.changeLetterState(letter, 'select'); } /** Проверяем значение тайла когда курсор над ним */ hoverLetter(letter: any) {; // Проверяем нажата ли кнопка мышки и есть ли ходы у игрока && > 0 && (() => { // Заносим букву в выбранные this.userSelect.push(letter.parent); // Меняем состояние буквы this.changeLetterState(letter, 'select'); })(); } /** Снимаем флаг нажатия когда пользователь отпустил клавишу */ removeSelectedLetter(letter:any) { let el: any, tw: any, tile: any; if(this.userSelect.length > 1) { this.debugDrawletterGrid(); while (!!this.userSelect.length) { tile = this.userSelect.shift(); ((sprite: any) => { let position = sprite.gridPosition; this.letterGrid[position.y][position.x] = null; /* tw =;{x: 0, y: 0}, 500, Phaser.Easing.Bounce.Out); tw.start(); tw.onComplete.add(() => {*/ sprite.destroy(); /*});*/ })(tile); = + 20; } this.userScore.text =; this.movesCounter.text =; this.resetTile(); this.debugDrawletterGrid(); } } debugDrawletterGrid() { var str: string = '', letterObj: any = ''; for (var i = 0; i < BOARD_COLS ; i++) { str = ''; for (var j = 0; j < BOARD_ROWS; j++) { letterObj = this.letterGrid[j][i]; if(!_.isNull(letterObj)) { if(letterObj.children.length && ('_text' in letterObj.children[0])) { str += '| ' + letterObj.children[0]._text + ' ';; } else { str += '| letter not exist';; } } else { str += '| ' + letterObj + ' '; } }; }'-----------------------------'); } } return Board; }); Game.ts: /// <reference path="def/p2.d.ts" /> /// <reference path="def/pixi.d.ts" /> /// <reference path="def/phaser.d.ts" /> /// <reference path="def/require.d.ts" /> /// <reference path="class/board.ts"/> define(['phaser', 'class/board'], function(Phaser, Board) { /** Start dictionary */ var dictionary = [ "нож", "стул", "стол", "карандаш", "паж" ], guessing = false; /** * Class representing game Wisdom of Atlantis */ class WisdomOfAtlantis { game: Phaser.Game; self: any; guessing: boolean = false; board: any; constructor() { = new Phaser.Game(GAME_ROOM_WIDTH, GAME_ROOM_HEIGHT, Phaser.AUTO, 'game-container', { preload: this.preload, create: this.create, update: this.update }); = 0; = 15; } /** Load game assets */ preload() { // Фон для игровой комнаты'game_room', '../img/bg/game_room.jpg'); // Фон игровых плиток (normal, hover, active)'field', '../img/bg/field_normal.png');'field_active', '../img/bg/field_active.png'); // Кнопка выхода'btn_exit', '../img/controls/buttons/exit.png', 76, 72, 3, 0, 10); // Кнопка подсказки'btn_help', '../img/controls/buttons/help.png', 76, 72, 3, 0, 10); // Кнопка вкл/вкл звук'btn_sound', '../img/controls/buttons/sound.png', 46, 42, 3, 0, 10); // Кнопка вкл/вкл музыку'btn_music', '../img/controls/buttons/music.png', 46, 42, 3, 0, 10); // Индикатор монет'btn_coin', '../img/controls/buttons/coin.png', 166, 84, 3); // Загружаем звуки и музыку'level_theme', '../audio/theme/level_v1.mp3');'tile_select', '../audio/effect/click.ogg');'tile_move', '../audio/effect/move.ogg');'add_score', '../audio/effect/addscore.ogg'); } /** Set game settings */ create() { // Фон игровой комнаты, 0, 'game_room'); // Обрабатываем нажатие мыши => { this.guessing = true; }); => { this.guessing = false; }); // Создаем доску this.board = new Board(; // Счетчик ходов this.board.movesCounter =, 45,, {font: "bold 68px Arial", fill: "#EEFF9C", boundsAlignH: "center", boundsAlignV: "middle"}); this.board.userScore = / 2) + 50, - 40,, {font: "bold 38px Arial", fill: "#EEFF9C", boundsAlignH: "center", boundsAlignV: "middle"});, 30, 'Xоды', { font: "bold 24px Arial", fill: "#EEFF9C", boundsAlignH: "center", boundsAlignV: "middle" }); // Заполняем доску буквами this.board.fill(); } /** Check game state and processing of a condition of game objects */ update() { if (!this.guessing) { this.board.removeSelectedLetter(); } } } return WisdomOfAtlantis; });
  11. Is it possible to create a group and configure in such a way that any child with position (0, 0) would be the center of the group instead of its top left corner? As I add bigger sprites to the group and its size increases, things get misaligned. The manual solution seems to involve re-adjusting the positions of the object in the group every time I add/remove something to it, which is kinda ugly.
  12. Hello, i'd like to know if there's any way to determine if a certain sprite is part of a certain group. More specifically, if i can check for collision between sprite and group, and make sure the sprite is colliding with another sprite that's part of a certain group. Thanks in advance.
  13. Learn numbers and counting. Now learning is so fun earn points with right answers but be careful every wrong answer will teke your points. Find hidden rabbits and give right answer every time. See the rabbits in action
  14. Hello, just want to know if this behavior is expected: when you set a Billboard mode to a mesh with a parent then the child mesh won't inherit scaling: Is there any way to avoid that? (other than changing the scaling to the child too)
  15. When trying to clean up my stage on game over, I loop through my game object groups and destroy all children inside explicitly. Then I destroy the (now empty) groups: cleanGroup(Grp1); // Grp1 is child of Stage groupcleanGroup(Grp2); // Grp2 is child of Stage groupcleanGroup(Grp3), // Grp3 is child of Stage groupcleanGroup(Stage);var cleanGroup = function(Grp) { if (Grp.children) { while (Grp.children.length) Grp.removeChildAt(0).destroy(); } Grp.destroy(); }However, this always gives me a hole bunch of error messages like: this.children is null this.parent is null o is null The error messages are constantly repeating as if it where within a loop anywhere inside the Pixi render enginge. Why is this and how could this be solved? Do I need to destroy my created sprites and groups at all or is it enough just to remove all of my references to them and let the garbage collection do the rest? Would this be reliable?
  16. I just noticed that changing the alpha value of a Container() does not affect any children within (actually, it does nothing). You have to set the alpha of each sprite within explicitly (which is really tedious). Why is that?
  17. We have just released a new game! COLORING BOOK: ANIMALS Take a look and tell us if you like it! High quality Graphics Optimized for mobile and desktop Code sources included Highly customizable Take a look also at our portfolio
  18. We Are Bionic is a creative digital studio looking to add fresh talent to our development team. Firmly established within the youth entertainment space, the studio works with organisations such as BBC, Channel5, Entertainment One and Disney delivering exciting browser based game experiences supporting TV brands. This role offers the opportunity for someone who has a real HTML5 game dev passion but wants the ability to be part of a small team helping to create fresh thinking around HTML5 gaming and drive the growth of the studio. The studio is based in South West London. If you are interested in hearing more about roles available or would like to meet up please drop an email to: [email protected] Thank you and looking forward to hearing from all candidates.
  19. Hi there, In the "group" tutorial ( it seems super easy to acces group elements, but for me it doesn't work. I have a simple project here: If you look in the play.js you can see the code. It's basically like this: this.playScreen = mt.create("Game"); // create Game Group this.gPig = this.playScreen.Pig; // but cannot get the children console.log("pig:" + this.gPig); // undefined - But Why? Any advise what the problem might be?
  20. I am using the Actions Manager and am trying to use the OnIntersectionEnterTrigger on a (child) mesh that has a parent, but seems to be firing on the parent mesh? Is this the right behavior? The mesh I would like for it to fire on is smaller than the overall parent mesh. Thanks.
  21. Looking for an artist for a chess game for children, with cute graphics in style of Kingdom Rush or Minecraft. Profit sharing possible. Thank you!
  22. Hello. I need to create a rectangular area in which the children can move inside it. The group have to work as a cropper, (a bit like a miniature of game world), in which the children will only display their part which still inside the area (some part outside the area will be cropped). When the children move back inside the area, it will partially displayed again until it is completely inside the area (which then shown it completely). Any idea how to implement this? Thank you
  23. Hey guys, I did a search of the forums as well as the Phaser/Pixi docs and came up short (let me know if it's answered anywhere else). I'm trying to create a mechanic whereby the player is able to pick up and drop sprites. I've been able to achieve pickups by using the group.add() function where the group parent is the player sprite, but when using .remove() to drop the sprite, the sprite just completely disappears. Its position, alpha, scale etc all look sensible and haven't been modified. What I have seen however is that the sprite parent name changes to being undefined, which seems unhealthy as when it spawns in the world its parent appears to be "__world". I also tried directly calling addChild() inherited from Pixi which is used in the Phaser groups, and the result was the same. It's easy to reproduce, my code is below. This is in .create() this.testGroup = this.testLight = game.add.sprite(300, 300, "buttonGradient");This is in .update() if (PLAYER_OBJECT.inputIsActive("y")) { this.testGroup.add(this.testLight); } if (PLAYER_OBJECT.inputIsActive("u")) { this.testGroup.remove(this.testLight); }Does anyone know if my setup is bad, or if there are other ways to achieve my desired effect? I had a look at the group remove example on the official examples page and the same thing happens there - I don't know if it's a bug or an intentional result of the system. Thanks in advance!
  24. Number Garden Arithmetic bugs from the forest of Lost algebra have taken over the park. Are you smart enough to help Lime and Minet the cat to stand against the neverending wave of maths bugs? Challenge yourself, learn maths and have fun. add them up in your head, no calculators, GO! Download the game from hereMore information about the game here Hi everybody!This is our first post here on the forum even if we have been lurking from a few months ago.We have just released our first game and we want to share it with you.Working with Phaser was a great pleasure: the documentation, the examples and the community support are just amazing! We created a game to help children (elementary - middle school) exercising their math skill while having fun. Nonetheless, we've heard that many adults are getting hooked up too. This is our first game ever so any feedback or comment is welcome. Thank your for your time
  25. Hi, welcome to my new project 'BALLON BEARS' This game was made with a younger audience in mind, so it has an easy to follow gameplay and cute cartoon style graphics. The game is still in development, not everything works as expected right now. All artwork was done by me. (I am available as a freelance artist, if you need some for your own projects feel free to get in contact with me). Please test the game and give me feedback! Link: