├── imports └── README.md ├── img ├── land.png ├── pipe.png ├── sky.png ├── 0_big.png ├── 1_big.png ├── 2_big.png ├── 3_big.png ├── 4_big.png ├── 5_big.png ├── 6_big.png ├── 7_big.png ├── 8_big.png ├── 9_big.png ├── ceiling.png ├── pipe_up.png ├── splash.png ├── pipe_down.png ├── bird_sprite.png └── bird_sprite@2x.png ├── INSTALL.md ├── README.md ├── Score.qml ├── birdy.qmlproject ├── DoublePipe.qml ├── main.qml ├── LICENSE ├── Floor.qml ├── Pipe.qml ├── ScoreBoard.qml ├── Birdy.qml ├── InfiniteScrollItem.qml └── MainScene.qml /imports/README.md: -------------------------------------------------------------------------------- 1 | place Bacon2D plugin here! 2 | -------------------------------------------------------------------------------- /img/land.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/land.png -------------------------------------------------------------------------------- /img/pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/pipe.png -------------------------------------------------------------------------------- /img/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/sky.png -------------------------------------------------------------------------------- /img/0_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/0_big.png -------------------------------------------------------------------------------- /img/1_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/1_big.png -------------------------------------------------------------------------------- /img/2_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/2_big.png -------------------------------------------------------------------------------- /img/3_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/3_big.png -------------------------------------------------------------------------------- /img/4_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/4_big.png -------------------------------------------------------------------------------- /img/5_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/5_big.png -------------------------------------------------------------------------------- /img/6_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/6_big.png -------------------------------------------------------------------------------- /img/7_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/7_big.png -------------------------------------------------------------------------------- /img/8_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/8_big.png -------------------------------------------------------------------------------- /img/9_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/9_big.png -------------------------------------------------------------------------------- /img/ceiling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/ceiling.png -------------------------------------------------------------------------------- /img/pipe_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/pipe_up.png -------------------------------------------------------------------------------- /img/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/splash.png -------------------------------------------------------------------------------- /img/pipe_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/pipe_down.png -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | Compile Bacon2D to you target architecture and place the result in the imports/ folder 2 | -------------------------------------------------------------------------------- /img/bird_sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/bird_sprite.png -------------------------------------------------------------------------------- /img/bird_sprite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulovap/bacon2d-flappybird/HEAD/img/bird_sprite@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bacon2d-flappybird 2 | ================== 3 | 4 | QML Bacon2D implementation of Flappy Bird game 5 | -------------------------------------------------------------------------------- /Score.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Row{ 4 | property int score: 0 5 | Repeater{ 6 | model:score.toString().length 7 | Image{ 8 | source: "img/XX_big.png".replace("XX", Number(String(score).charAt(index))) 9 | } 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /birdy.qmlproject: -------------------------------------------------------------------------------- 1 | import QmlProject 1.1 2 | 3 | Project { 4 | mainFile: "main.qml" 5 | 6 | /* Include .qml, .js, and image files from current directory and subdirectories */ 7 | QmlFiles { 8 | directory: "." 9 | } 10 | JavaScriptFiles { 11 | directory: "." 12 | } 13 | ImageFiles { 14 | directory: "img" 15 | } 16 | /* List of plugin directories passed to QML runtime */ 17 | importPaths: [ "imports", "Bacon2D" ] // <- Bacon2D folder goes here! 18 | } 19 | -------------------------------------------------------------------------------- /DoublePipe.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Bacon2D 1.0 3 | 4 | Entity{ 5 | id:root 6 | 7 | property real bodyX; 8 | property int gapY 9 | property int gapHeight 10 | 11 | signal touched(var other) 12 | width:pipeUp.width 13 | Pipe{ 14 | id:pipeUp 15 | headUp: false 16 | x:bodyX 17 | height: gapY 18 | onTouched: root.touched(other) 19 | } 20 | Pipe{ 21 | x:bodyX; y: gapY + gapHeight 22 | height: parent.height -gapY -gapHeight 23 | headUp: true 24 | onTouched: root.touched(other) 25 | } 26 | 27 | behavior: ScriptBehavior{ 28 | script: { 29 | root.bodyX-= 1.5 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | /* main.qml 2 | * 3 | * Copyright (C) 2014 Paulo Pinheiro 4 | * 5 | * This software may be modified and distributed under the terms 6 | * of the MIT license. See the LICENSE file for details. 7 | */ 8 | import QtQuick 2.2 9 | import Bacon2D 1.0 10 | 11 | Game{ 12 | id:game 13 | gameName: "Jumpy Bird" 14 | width: 640 15 | height: 420 16 | ups:30 // <- updates per second 17 | currentScene: scene 18 | 19 | states: [ 20 | State { 21 | name: "over" 22 | PropertyChanges { 23 | target: textGameOver 24 | opacity: 1 25 | scale:2.4 26 | } 27 | } 28 | ] 29 | 30 | MainScene{ 31 | id:scene 32 | width: parent.width; height:parent.height 33 | } 34 | 35 | 36 | 37 | Image{ 38 | source:"img/splash.png" 39 | visible: !scene.running 40 | anchors{ 41 | centerIn: parent 42 | verticalCenterOffset: -20 43 | } 44 | z:2 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the "Software"), to deal 3 | in the Software without restriction, including without limitation the rights 4 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /Floor.qml: -------------------------------------------------------------------------------- 1 | /* Floor.qml 2 | * 3 | * Copyright (C) 2014 Paulo Pinheiro 4 | * 5 | * This software may be modified and distributed under the terms 6 | * of the MIT license. See the LICENSE file for details. 7 | */ 8 | 9 | import QtQuick 2.3 10 | import Bacon2D 1.0 11 | 12 | Item{ 13 | id:floor 14 | 15 | property Scene scene 16 | 17 | signal touchedFloor(var other) 18 | 19 | visible:true 20 | 21 | BoxBody{ 22 | id:body 23 | target: floor 24 | world: scene.world 25 | bodyType: Body.Static 26 | width:floor.width; height:floor.height 27 | density:1 28 | friction: 1 29 | sensor:false 30 | onBeginContact: touchedFloor(other) 31 | } 32 | 33 | InfiniteScrollItem{ 34 | id:scrollItem 35 | Image{ 36 | width: floor.width; height: floor.height 37 | source: "img/land.png" 38 | fillMode: Image.Tile 39 | } 40 | } 41 | Timer{ 42 | running:scene.running 43 | interval: 16 44 | repeat: true 45 | onTriggered: scrollItem.offsetX +=0.3 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Pipe.qml: -------------------------------------------------------------------------------- 1 | /* Pipe.qml 2 | * 3 | * Copyright (C) 2014 Paulo Pinheiro 4 | * 5 | * This software may be modified and distributed under the terms 6 | * of the MIT license. See the LICENSE file for details. 7 | */ 8 | 9 | import QtQuick 2.0 10 | import Bacon2D 1.0 11 | 12 | PhysicsEntity { 13 | id:root 14 | property bool headUp: true 15 | 16 | signal touched(var other) 17 | 18 | width: pipeBody.width 19 | 20 | fixedRotation: true 21 | bodyType: Body.Static 22 | //physics 23 | fixtures:[ 24 | Box{ 25 | id:boxBody 26 | width: root.width; height: root.height 27 | density:1 28 | friction: 1 29 | sensor:false 30 | onBeginContact: root.touched(other) 31 | } 32 | 33 | ] 34 | Image{ 35 | id:pipeBody 36 | y: headUp ? imageHead.height : 0 37 | height:parent.height - imageHead.height 38 | source: "img/pipe.png" 39 | fillMode: Image.Tile 40 | } 41 | Image{ 42 | id:imageHead 43 | y: headUp ? 0 : parent.height - height; 44 | source: headUp ? "img/pipe_up.png" : "img/pipe_down.png" 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /ScoreBoard.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 1.1 3 | import QtQuick.Layouts 1.1 4 | 5 | Item { 6 | id:root 7 | width: 300 8 | height: 400 9 | 10 | property string score: "" 11 | property string highScore: "" 12 | 13 | ColumnLayout{ 14 | Text { 15 | id: text 16 | text: qsTr("Game Over") 17 | font.bold: true 18 | horizontalAlignment: Text.AlignHCenter 19 | font.pixelSize: 28 20 | 21 | } 22 | 23 | Text { 24 | id: text1 25 | text:root.score 26 | font.bold: true 27 | horizontalAlignment: Text.AlignHCenter 28 | font.pixelSize: 28 29 | } 30 | 31 | Text { 32 | id: text2 33 | text: "High Score" 34 | font.bold: true 35 | horizontalAlignment: Text.AlignHCenter 36 | font.pixelSize: 28 37 | } 38 | 39 | Text { 40 | id: text3 41 | text: root.highScore 42 | font.bold: true 43 | horizontalAlignment: Text.AlignHCenter 44 | font.pixelSize: 28 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Birdy.qml: -------------------------------------------------------------------------------- 1 | /* Birdy.qml 2 | * 3 | * Copyright (C) 2014 Paulo Pinheiro 4 | * 5 | * This software may be modified and distributed under the terms 6 | * of the MIT license. See the LICENSE file for details. 7 | */ 8 | 9 | import QtQuick 2.3 10 | import Bacon2D 1.0 11 | 12 | Entity{ 13 | id:root 14 | width:60;height:50 15 | transformOrigin: Item.TopLeft 16 | 17 | 18 | BoxBody{ 19 | id:circleBody 20 | world: root.scene.world 21 | target: root 22 | width: root.width - 20 23 | height: root.height - 20 24 | density: 0.5 25 | friction: 1 26 | restitution: 0.2 27 | fixedRotation: true 28 | bodyType: Body.Dynamic 29 | } 30 | 31 | function jump(){ 32 | state = "jumping" 33 | var oldVel = circleBody.linearVelocity 34 | circleBody.linearVelocity = Qt.point(oldVel.x, -4) 35 | } 36 | 37 | Sprite { 38 | id: birdy 39 | anchors.fill: parent 40 | spriteState: scene.running ? Bacon2D.Running : Bacon2D.Paused 41 | property bool jumping: false 42 | 43 | animation: "flying" 44 | 45 | states: [ 46 | State { 47 | name: "jumping" 48 | PropertyChanges { 49 | target: birdy 50 | jumping:true 51 | 52 | } 53 | } 54 | ] 55 | 56 | animations: [ 57 | SpriteAnimation { 58 | name: "flying" 59 | source: "img/bird_sprite.png" 60 | frames: 3 61 | duration: 400 62 | loops: Animation.Infinite 63 | } 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /InfiniteScrollItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | 3 | /*! 4 | \qmltype InfiniteScrollItem 5 | \inqmlmodule Bacon2D 6 | \inherits Item 7 | \ingroup graphics 8 | \brief Enable an Item to do a infinite scroll. Good for moving background 9 | */ 10 | Item { 11 | id:root 12 | 13 | /*! 14 | \qmlproperty Item InfiniteScrollItem::target 15 | \brief \l Item that will used as texture for scrolling effect. 16 | */ 17 | default property Item target 18 | 19 | /*! 20 | \qmlproperty Item InfiniteScrollItem::offsetX 21 | \brief \l The amount of vertical pixels that will be shifted. 22 | */ 23 | property real offsetX: 0; 24 | /*! 25 | \qmlproperty Item InfiniteScrollItem::offsetY 26 | \brief \l The amount of horizontal pixels that will be shifted 27 | */ 28 | property real offsetY: 0; 29 | 30 | implicitWidth: target.width 31 | implicitHeight: target.height 32 | 33 | ShaderEffectSource{ 34 | id:shaderSource 35 | width: target.width; height:target.height 36 | sourceItem: target 37 | hideSource:true 38 | visible:false 39 | } 40 | 41 | ShaderEffect { 42 | id:shader 43 | width: target.width; height:target.height 44 | 45 | property real shaderXStep: target ? offsetX / target.height : 0 46 | property real shaderYStep: target ? offsetY / target.width : 0 47 | 48 | property Item target: shaderSource 49 | 50 | blending: false 51 | vertexShader: " 52 | uniform highp mat4 qt_Matrix; 53 | attribute highp vec4 qt_Vertex; 54 | attribute highp vec2 qt_MultiTexCoord0; 55 | varying highp vec2 coord; 56 | void main() { 57 | coord = qt_MultiTexCoord0; 58 | gl_Position = qt_Matrix * qt_Vertex; 59 | }" 60 | fragmentShader: " 61 | uniform float width; 62 | uniform lowp float qt_Opacity; 63 | uniform sampler2D target; 64 | uniform float shaderXStep; 65 | uniform float shaderYStep; 66 | varying highp vec2 coord; 67 | void main(void) { 68 | vec4 texel = texture2D(target, vec2(mod(coord.x + shaderXStep, 1.0), mod(coord.y + shaderYStep, 1.0))); 69 | gl_FragColor = texel * qt_Opacity; 70 | } " 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /MainScene.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import Bacon2D 1.0 3 | 4 | Scene{ 5 | id:scene 6 | 7 | property var pipes: [] 8 | 9 | state: "newgame" 10 | states:[ 11 | State{ 12 | name:"newgame" 13 | StateChangeScript{ script:reset() } 14 | }, 15 | State{ 16 | name:"endgame" 17 | } 18 | ] 19 | 20 | physics: true 21 | gravity: Qt.point(0,9.8) 22 | pixelsPerMeter:18 23 | 24 | Keys.onUpPressed: bird.jump() 25 | 26 | function reset(){ 27 | bird.x = 50; 28 | bird.y = 200; 29 | game.gameState = Bacon2D.Running 30 | 31 | pipes.forEach(function(pipe){ pipe.destroy() }); 32 | pipes = [] 33 | scoreItem.score = 0 34 | } 35 | 36 | /* 37 | sky blue background 38 | */ 39 | Rectangle{ 40 | anchors.fill: parent 41 | color:"#4ec0ca" 42 | } 43 | 44 | /* 45 | parallax part of background. Cities and clouds 46 | */ 47 | InfiniteScrollItem{ 48 | id:scrollItem 49 | anchors{ 50 | bottom:parent.bottom; bottomMargin: floor.height; 51 | horizontalCenter: parent.horizontalCenter} 52 | Image{ 53 | scale:1 54 | width:scene.width 55 | source: "img/sky.png" 56 | fillMode: Image.Tile 57 | Timer{ 58 | running:scene.running 59 | interval: 16 60 | repeat: true 61 | onTriggered: scrollItem.offsetX +=0.02 62 | } 63 | } 64 | } 65 | 66 | Score{ 67 | id:scoreItem 68 | anchors{ 69 | horizontalCenter: parent.horizontalCenter; 70 | top:parent.top; topMargin: 20 71 | } 72 | score: 0 73 | z:10 74 | } 75 | /* 76 | player entity 77 | */ 78 | Birdy{ 79 | id:bird 80 | x:50; y:200; 81 | } 82 | 83 | Component{ 84 | id:pipeComponent 85 | DoublePipe{ 86 | id:dp 87 | property bool passed: false 88 | bodyX:scene.width + 10 89 | onTouched: scene.game.gameState = Bacon2D.Suspended 90 | height: parent.height 91 | gapY: 100 92 | gapHeight: 100 93 | 94 | onBodyXChanged: { 95 | if(bodyX < bird.x && !passed){ 96 | scoreItem.score++ 97 | passed = true 98 | } 99 | } 100 | } 101 | } 102 | 103 | Floor{ 104 | id:floor 105 | 106 | anchors.left: scene.left 107 | anchors.bottom: scene.bottom 108 | 109 | width: parent.width; height:112 110 | scene: scene 111 | z:2 112 | 113 | onTouchedFloor: game.gameState = Bacon2D.Suspended 114 | } 115 | 116 | Timer{ 117 | 118 | id:pipeGenerator 119 | interval:2500; repeat: true 120 | running:scene.running 121 | 122 | onTriggered: { 123 | var pipe = pipeComponent.createObject(scene, {gapY:60 + Math.floor(Math.random()*10)*0.1*80}) 124 | pipes.push(pipe) 125 | } 126 | } 127 | 128 | MultiPointTouchArea{ 129 | anchors.fill: parent 130 | maximumTouchPoints: 1 131 | mouseEnabled: true 132 | onPressed: if(scene.running) bird.jump(); else reset(); 133 | } 134 | } 135 | --------------------------------------------------------------------------------