summaryrefslogtreecommitdiff
path: root/src/samples
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
committerDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
commitdd22bd15f6ed3e5eb5c77ab427029be50fe20148 (patch)
treed9491ee40d80688b7f5b1f20504f022686827a57 /src/samples
libavg (1.8.1-1) unstable; urgency=medium
* New upstream release (Closes: #739664) * Mark libdc1394-22-dev as linux-any build-dependency. * Add libvdpau-dev build-dependency. * Add libavresample-dev build-dependency. # imported from the archive
Diffstat (limited to 'src/samples')
-rw-r--r--src/samples/Makefile.am5
-rwxr-xr-xsrc/samples/abort_gestures.py114
-rwxr-xr-xsrc/samples/anim1.py17
-rwxr-xr-xsrc/samples/anim2.py19
-rwxr-xr-xsrc/samples/app_complete.py58
-rwxr-xr-xsrc/samples/app_minimal.py17
-rwxr-xr-xsrc/samples/asyncload.py89
-rwxr-xr-xsrc/samples/attributes.py11
-rwxr-xr-xsrc/samples/canvas.py14
-rwxr-xr-xsrc/samples/drag.py36
-rwxr-xr-xsrc/samples/event1.py20
-rwxr-xr-xsrc/samples/event2.py21
-rw-r--r--src/samples/firebirds/LICENSE6
-rw-r--r--src/samples/firebirds/Makefile.am3
-rwxr-xr-xsrc/samples/firebirds/firebirds.py469
-rw-r--r--src/samples/firebirds/media/Fire_Birds.mp3bin0 -> 1824809 bytes
-rw-r--r--src/samples/firebirds/media/Makefile.am5
-rw-r--r--src/samples/firebirds/media/bullet.gifbin0 -> 188 bytes
-rw-r--r--src/samples/firebirds/media/bullet.movbin0 -> 37232 bytes
-rw-r--r--src/samples/firebirds/media/bulletSound.mp3bin0 -> 20062 bytes
-rw-r--r--src/samples/firebirds/media/enemy.gifbin0 -> 1123 bytes
-rw-r--r--src/samples/firebirds/media/enemy.movbin0 -> 603181 bytes
-rw-r--r--src/samples/firebirds/media/enemyDeath.mp3bin0 -> 63529 bytes
-rw-r--r--src/samples/firebirds/media/explosion.movbin0 -> 2218276 bytes
-rw-r--r--src/samples/firebirds/media/flySound.mp3bin0 -> 193097 bytes
-rw-r--r--src/samples/firebirds/media/ground.jpgbin0 -> 262162 bytes
-rw-r--r--src/samples/firebirds/media/gui_frame.pngbin0 -> 124453 bytes
-rw-r--r--src/samples/firebirds/media/gui_heatbar_bg.pngbin0 -> 12626 bytes
-rw-r--r--src/samples/firebirds/media/gui_heatbar_fg.pngbin0 -> 13937 bytes
-rw-r--r--src/samples/firebirds/media/gui_lives_bg.pngbin0 -> 3679 bytes
-rw-r--r--src/samples/firebirds/media/gui_lives_fg.pngbin0 -> 4655 bytes
-rw-r--r--src/samples/firebirds/media/gui_numbers.pngbin0 -> 12640 bytes
-rw-r--r--src/samples/firebirds/media/spitfire.gifbin0 -> 1109 bytes
-rw-r--r--src/samples/firebirds/media/spitfire.movbin0 -> 612657 bytes
-rw-r--r--src/samples/firebirds/plugin/CollisionDetector.cpp122
-rw-r--r--src/samples/firebirds/plugin/CollisionDetector.h28
-rw-r--r--src/samples/firebirds/plugin/Makefile.am16
-rw-r--r--src/samples/flashmessages.py58
-rwxr-xr-xsrc/samples/fontstyle.py23
-rwxr-xr-xsrc/samples/gestures.py287
-rwxr-xr-xsrc/samples/globalcoords.py9
-rwxr-xr-xsrc/samples/invertfx.py35
-rwxr-xr-xsrc/samples/localcoords.py10
-rwxr-xr-xsrc/samples/localcoordsrot.py11
-rwxr-xr-xsrc/samples/logsample.py55
-rwxr-xr-xsrc/samples/mesh.py13
-rwxr-xr-xsrc/samples/minimal.py9
-rw-r--r--src/samples/mpeg1-48x48-sound.avibin0 -> 28534 bytes
-rwxr-xr-xsrc/samples/plugin.py15
-rw-r--r--src/samples/rgb24-64x64.pngbin0 -> 2092 bytes
-rwxr-xr-xsrc/samples/rotcustompivot.py11
-rwxr-xr-xsrc/samples/rotdefaultpivot.py11
-rwxr-xr-xsrc/samples/showvideo.py14
-rwxr-xr-xsrc/samples/slideshow.py159
-rwxr-xr-xsrc/samples/subclass.py40
-rwxr-xr-xsrc/samples/timer.py16
-rwxr-xr-xsrc/samples/timer2.py17
-rwxr-xr-xsrc/samples/timer3.py19
-rwxr-xr-xsrc/samples/twovideos.py55
-rwxr-xr-xsrc/samples/video.py11
-rwxr-xr-xsrc/samples/videochooser.py87
-rwxr-xr-xsrc/samples/widget.py77
-rwxr-xr-xsrc/samples/wordspos.py15
63 files changed, 2127 insertions, 0 deletions
diff --git a/src/samples/Makefile.am b/src/samples/Makefile.am
new file mode 100644
index 0000000..8af2a57
--- /dev/null
+++ b/src/samples/Makefile.am
@@ -0,0 +1,5 @@
+EXTRA_DIST = $(wildcard *.avg) $(wildcard *.png) $(wildcard *.avi)
+pkgsampledir = $(pkgpyexecdir)/samples
+pkgsample_PYTHON = $(wildcard *.py)
+pkgsample_DATA = $(wildcard *.avg) $(wildcard *.png) $(wildcard *.avi)
+SUBDIRS = firebirds
diff --git a/src/samples/abort_gestures.py b/src/samples/abort_gestures.py
new file mode 100755
index 0000000..f948805
--- /dev/null
+++ b/src/samples/abort_gestures.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, gesture, app
+
+import gestures
+
+RESOLUTION = avg.Point2D(800, 600)
+
+nodeList = []
+nodesEnabled = True
+
+def abortAll():
+ for node in nodeList:
+ node.recognizer.abort()
+
+def switchNodesEnabled():
+ global nodesEnabled
+ nodesEnabled = not nodesEnabled
+ for node in nodeList:
+ node.recognizer.enable(nodesEnabled)
+
+
+class TapButton(gestures.TextRect):
+ def __init__(self, text, **kwargs):
+ super(TapButton, self).__init__(text, **kwargs)
+
+ self.recognizer = gesture.TapRecognizer(node=self,
+ possibleHandler=self._onPossible, detectedHandler=self._onDetected,
+ failHandler=self._onFail)
+
+ def _onPossible(self):
+ self.rect.fillcolor = "FFFFFF"
+
+ def _onDetected(self):
+ self.rect.fillcolor = "000000"
+ self.rect.color = "00FF00"
+
+ def _onFail(self):
+ self.rect.fillcolor = "000000"
+ self.rect.color = "FF0000"
+
+
+class AbortButton(TapButton):
+ def __init__(self, text, **kwargs):
+ super(AbortButton, self).__init__(text, **kwargs)
+
+ def _onPossible(self):
+ super(AbortButton, self)._onPossible()
+ self.words.color = "000000"
+
+ def _onDetected(self):
+ super(AbortButton, self)._onDetected()
+ abortAll()
+ self.words.color = "FFFFFF"
+
+ def _onFail(self):
+ super(AbortButton, self)._onFail()
+ self.words.color = "FFFFFF"
+
+
+class EnableButton(TapButton):
+ def __init__(self, text, **kwargs):
+ super(EnableButton, self).__init__(text, **kwargs)
+
+ self.words.color = "FF0000"
+
+ def changeText(self):
+ if(nodesEnabled):
+ self.words.text = "Disable all"
+ self.words.color = "FF0000"
+ else:
+ self.words.text = "Enable all"
+ self.words.color = "00FF00"
+
+ def _onDetected(self):
+ super(EnableButton, self)._onDetected()
+ switchNodesEnabled()
+ self.changeText()
+
+
+class GestureDemoDiv(app.MainDiv):
+
+ def onInit(self):
+
+ avg.WordsNode(text='''a - abort recognition <br/>
+ d - enable/disable recognition <br/><br/>
+ or use the buttons on the right side''',
+ pos=(20, 510), parent=self)
+
+ nodeList.append(gestures.HoldNode(text="HoldRecognizer", pos=(20,20), parent=self))
+
+ nodeList.append(gestures.DragNode(text="DragRecognizer<br/>friction",pos=(200,20),
+ friction=0.05, parent=self))
+
+ nodeList.append(gestures.TransformNode(text="TransformRecognizer",
+ ignoreRotation=False, ignoreScale=False, pos=(380,20), parent=self))
+
+ self.abortButton = AbortButton(text="Abort all", pos = (630, 490), parent=self)
+
+ self.enableButton = EnableButton(text="Disable all", pos = (630, 540), parent=self)
+
+ app.keyboardmanager.bindKeyDown(keystring="a", handler=abortAll,
+ help="abort recognition")
+ app.keyboardmanager.bindKeyDown(keystring="d", handler=self.onEnableKey,
+ help="Enable/disable recognition")
+
+ def onEnableKey(self):
+ switchNodesEnabled()
+ self.enableButton.changeText()
+
+
+if __name__ == '__main__':
+ app.App().run(GestureDemoDiv(), app_resolution="800,600")
diff --git a/src/samples/anim1.py b/src/samples/anim1.py
new file mode 100755
index 0000000..0e78c02
--- /dev/null
+++ b/src/samples/anim1.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import *
+
+def startAnim():
+ animObj.start()
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+
+animObj = LinearAnim(node, "x", 2000, 0, 200)
+player.setTimeout(0, startAnim)
+
+player.play()
+
diff --git a/src/samples/anim2.py b/src/samples/anim2.py
new file mode 100755
index 0000000..f48106f
--- /dev/null
+++ b/src/samples/anim2.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import *
+
+def startAnim():
+ animObj.start()
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+
+animObj = ParallelAnim(
+ [LinearAnim(node, "x", 2000, 0, 200),
+ LinearAnim(node, "y", 2000, 0, 10)])
+player.setTimeout(0, startAnim)
+
+player.play()
+
diff --git a/src/samples/app_complete.py b/src/samples/app_complete.py
new file mode 100755
index 0000000..ac4af8d
--- /dev/null
+++ b/src/samples/app_complete.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import libavg
+from libavg import app, player
+
+
+class MyMainDiv(app.MainDiv):
+ # An OptionParser instance is passed to this function, allowing the MainDiv to
+ # add command line arguments
+ def onArgvParserCreated(self, parser):
+ parser.add_option('--speed', '-s', default='0.3', dest='speed',
+ help='Pixels per second')
+ parser.add_option('--color', '-c', default='ff0000', dest='color',
+ help='Fill color of the running block')
+
+ # This method is called when the command line options are being parsed.
+ # options, args are the result of OptionParser.parse_args().
+ def onArgvParsed(self, options, args, parser):
+ self.argvoptions = options
+
+ # This is called as soon as the player is started by the App object.
+ # Initialize everything here.
+ def onInit(self):
+ libavg.WordsNode(text='block_speed=%s app_resolution=%s' %
+ (self.argvoptions.speed,
+ self.settings.getPoint2D('app_resolution')),
+ pos=(10, self.height - 25), parent=self)
+
+ # Create a graphic element that will be animated
+ self.__runningBlock = libavg.RectNode(pos=(0, 100), size=(20, 20),
+ fillopacity=1, fillcolor=self.argvoptions.color,
+ parent=self)
+ self.__shouldMove = True
+
+ app.keyboardmanager.bindKeyDown('m', self.__toggleMotion, 'Toggle motion')
+
+ def onExit(self):
+ print 'Exiting..'
+
+ def onFrame(self):
+ if self.__shouldMove:
+ speed = float(self.argvoptions.speed)
+ self.__runningBlock.pos += (speed * player.getFrameDuration(), 0)
+ if self.__runningBlock.pos.x > self.size.x:
+ self.__runningBlock.pos = (0, 100)
+
+ def __toggleMotion(self):
+ self.__shouldMove = not self.__shouldMove
+ # Flash messages are debug notifications that are shown temporarily on top of all
+ # the visible elements.
+ app.flashmessage.FlashMessage('Should move: %s' % self.__shouldMove)
+
+
+if __name__ == '__main__':
+ # App options (such as app_resolution) can be changed as parameters of App().run()
+ app.App().run(MyMainDiv(), app_resolution='1024x500')
+
diff --git a/src/samples/app_minimal.py b/src/samples/app_minimal.py
new file mode 100755
index 0000000..230b98f
--- /dev/null
+++ b/src/samples/app_minimal.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import app
+
+class MyMainDiv(app.MainDiv):
+ def onInit(self):
+ pass
+
+ def onExit(self):
+ pass
+
+ def onFrame(self):
+ pass
+
+app.App().run(MyMainDiv())
+
diff --git a/src/samples/asyncload.py b/src/samples/asyncload.py
new file mode 100755
index 0000000..48f15db
--- /dev/null
+++ b/src/samples/asyncload.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+'''
+Shows how to use BitmapManager to asynchronously load a Bitmap from a file.
+Run this snippet providing a list of filenames of (high resolution) pictures:
+
+$ ./asyncload.py /path/to/mypics/*.jpg anotherpic.png nonexistent.png
+
+Press space to sequentially load the pictures. A rotating rectangle appears
+during the time the picture file is being loaded to show how the main thread
+is not affected by the load operation.
+
+Press 'f' to display the frame time graph, which should show no significant
+glitches while loading
+'''
+
+import sys
+from libavg import avg, player, app
+
+APP_RESOLUTION = (640, 480)
+
+
+class AsyncLoadDiv(app.MainDiv):
+
+ def onInit(self):
+ '''
+ Create placeholders for the example. A single ImageNode is used to show
+ the pictures.
+ '''
+ self.__imageNode = avg.ImageNode(pos=(10, 20), parent=self)
+ self.__spinner = avg.RectNode(color='222222', fillopacity=1, size=(40, 40),
+ active=False, pos=(10, self.size.y - 50), parent=self)
+ self.__infoNode = avg.WordsNode(text='Press space to load the first image',
+ fontsize=11, pos=(10, 5), parent=self)
+
+ self.__pics = sys.argv[1:]
+ self.__currentPic = -1
+ player.subscribe(player.ON_FRAME, self.__onFrame)
+ app.keyboardmanager.bindKeyDown(keystring="space", handler=self.__requestNextBitmap,
+ help="Request next bitmap")
+
+ def __requestNextBitmap(self):
+ '''
+ Ask the BitmapManager to load a new file. loadBitmap() call returns immediately.
+ '''
+ self.__currentPic = (self.__currentPic + 1) % len(self.__pics)
+ avg.BitmapManager.get().loadBitmap(self.__pics[self.__currentPic],
+ self.__onBitmapLoaded)
+
+ self.__spinner.active = True
+ self.__spinner.angle = 0
+
+ def __onBitmapLoaded(self, bmp):
+ '''
+ This callback is invoked by BitmapManager, 'bmp' can be either a Bitmap instance
+ or a RuntimeError instance (hence checking for Exception is consistent).
+ '''
+ self.__spinner.active = False
+ if isinstance(bmp, Exception):
+ self.__infoNode.text = ('Error loading '
+ 'image %s : %s' % (self.__pics[self.__currentPic], str(bmp)))
+ self.__imageNode.href = ''
+ else:
+ self.__infoNode.text = ('Loaded %s, '
+ 'press space for the next one' % self.__pics[self.__currentPic])
+ self.__setBitmapAndResize(bmp)
+
+ def __setBitmapAndResize(self, bmp):
+ originalSize = bmp.getSize()
+
+ if originalSize.x > originalSize.y:
+ ratio = (APP_RESOLUTION[0] - 20) / originalSize.x
+ else:
+ ratio = (APP_RESOLUTION[1] - 40) / originalSize.y
+
+ self.__imageNode.setBitmap(bmp)
+ self.__imageNode.size = originalSize * ratio
+
+ def __onFrame(self):
+ if self.__spinner.active:
+ self.__spinner.angle += 0.05
+
+if len(sys.argv) == 1:
+ print 'Usage: %s <filename> [<filename> [<filename> [..]]]' % sys.argv[0]
+ sys.exit(1)
+
+app.App().run(AsyncLoadDiv(), app_resolution="640,480")
+
diff --git a/src/samples/attributes.py b/src/samples/attributes.py
new file mode 100755
index 0000000..b4aa6d4
--- /dev/null
+++ b/src/samples/attributes.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+print node.x
+node.x = 200
+player.play()
diff --git a/src/samples/canvas.py b/src/samples/canvas.py
new file mode 100755
index 0000000..ad5bb2b
--- /dev/null
+++ b/src/samples/canvas.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+offscreenCanvas = player.createCanvas(id="londoncalling", size=(320,240))
+avg.WordsNode(pos=(10,10), text="London Calling",
+ parent=offscreenCanvas.getRootNode())
+
+mainCanvas = player.createMainCanvas(size=(640,480))
+rootNode = mainCanvas.getRootNode()
+avg.ImageNode(href="canvas:londoncalling", parent=rootNode)
+
+player.play()
diff --git a/src/samples/drag.py b/src/samples/drag.py
new file mode 100755
index 0000000..e5d50e7
--- /dev/null
+++ b/src/samples/drag.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+offset = None
+
+def onMouseDown(event):
+ global offset
+ node = event.node
+ offset = node.getRelPos((event.x, event.y))
+ node.setEventCapture()
+
+def onMouseMove(event):
+ global offset
+ node = event.node
+ if offset != None:
+ node.x = event.x-offset[0]
+ node.y = event.y-offset[1]
+
+def onMouseUp(event):
+ global offset
+ node = event.node
+ if offset != None:
+ node.releaseEventCapture()
+ offset = None;
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+node.subscribe(node.CURSOR_DOWN, onMouseDown)
+node.subscribe(node.CURSOR_MOTION, onMouseMove)
+node.subscribe(node.CURSOR_UP, onMouseUp)
+
+player.play()
+
diff --git a/src/samples/event1.py b/src/samples/event1.py
new file mode 100755
index 0000000..d0de427
--- /dev/null
+++ b/src/samples/event1.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+def onMouseOver(event):
+ global node
+ node.color = "FF8000"
+
+def onMouseOut(event):
+ global node
+ node.color = "FFFFFF"
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+node.subscribe(node.CURSOR_OVER, onMouseOver)
+node.subscribe(node.CURSOR_OUT, onMouseOut)
+player.play()
+
diff --git a/src/samples/event2.py b/src/samples/event2.py
new file mode 100755
index 0000000..6e7de63
--- /dev/null
+++ b/src/samples/event2.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+def onDiv(event):
+ words.color = "FF8000"
+
+def onWords(event):
+ words.color = "00FF00"
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+words = avg.WordsNode(pos=(10,10), text="Should I stay or should I go?",
+ parent=rootNode)
+div = avg.DivNode(pos=(100,0), size=(80,200), parent=rootNode)
+words.subscribe(words.CURSOR_MOTION, onWords)
+div.subscribe(div.CURSOR_MOTION, onDiv)
+
+player.play()
+
diff --git a/src/samples/firebirds/LICENSE b/src/samples/firebirds/LICENSE
new file mode 100644
index 0000000..8da327f
--- /dev/null
+++ b/src/samples/firebirds/LICENSE
@@ -0,0 +1,6 @@
+Firebirds is a rewrite of the firebirds game published for an XNA tutorial by
+the magazine c't (9/2011, p 184) and developed by Alfred Bigler.
+
+The images, videos and sounds in the media/ directory are Copyright (C) Alfred
+Bigler and distributed under the CC BY-SA 3.0 License by his permission. See
+http://creativecommons.org/licenses/by-sa/3.0/ for the complete license text.
diff --git a/src/samples/firebirds/Makefile.am b/src/samples/firebirds/Makefile.am
new file mode 100644
index 0000000..c574414
--- /dev/null
+++ b/src/samples/firebirds/Makefile.am
@@ -0,0 +1,3 @@
+pkgtutorialdir = $(pkgpyexecdir)/samples/firebirds
+pkgtutorial_PYTHON = $(wildcard *.py)
+SUBDIRS = plugin media
diff --git a/src/samples/firebirds/firebirds.py b/src/samples/firebirds/firebirds.py
new file mode 100755
index 0000000..3656255
--- /dev/null
+++ b/src/samples/firebirds/firebirds.py
@@ -0,0 +1,469 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# libavg - Media Playback Engine.
+# Copyright (C) 2012-2013 Ulrich von Zadow
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Current versions can be found at www.libavg.de
+#
+# Original author of this file: Thomas Schott <scotty@c-base.org>
+
+# See the LICENSE file for license information regarding the media
+# used by this sample.
+
+from random import randint
+
+from libavg import avg, player
+from libavg import app
+from libavg.utils import getMediaDir
+
+player.loadPlugin('collisiondetector')
+
+def playVideo(video):
+ if not player.isUsingGLES():
+ video.play()
+
+
+### game elements ###
+
+class Bullet(avg.VideoNode):
+ __SPEED = 360 # px/s
+
+ def __init__(self, parent=None, **kwargs):
+ super(Bullet, self).__init__(href='bullet.mov', loop=True, active=False, **kwargs)
+ self.registerInstance(self, parent)
+ self.pause()
+
+ def reset(self, pos):
+ self.pos = pos
+ self.active = True
+ playVideo(self)
+
+ def update(self, dt):
+ y = self.y - Bullet.__SPEED * dt
+ if y > -self.height:
+ self.y = y
+ else:
+ self.destroy()
+
+ def destroy(self):
+ self.active = False
+ self.pause()
+
+
+class _Aircraft(avg.DivNode):
+ _SPEED = 300 # px/s
+ __SHADOW_SCALE = 0.5
+ __SHADOW_OFFSET = avg.Point2D(170, 170)
+
+ def __init__(self, mediabase, shadowdiv, parent=None, **kwargs):
+ super(_Aircraft, self).__init__(**kwargs)
+ self.registerInstance(self, parent)
+ self.__alive = False
+ self.__aircraftVid = avg.VideoNode(href=mediabase+'.mov', loop=True, parent=self)
+ self.__aircraftVid.pause()
+ self.__destroyVid = avg.VideoNode(href='explosion.mov', active=False,
+ threaded=False, parent=self)
+ self.__destroyVid.pause()
+ self.__destroyVid.subscribe(avg.VideoNode.END_OF_FILE, self._hide)
+ self.__shadowImg = avg.ImageNode(href=mediabase+'.gif', opacity=0.5,
+ pos=self.pos + _Aircraft.__SHADOW_OFFSET, parent=shadowdiv)
+ self.__shadowImg.size *= _Aircraft.__SHADOW_SCALE
+ if not player.isUsingGLES():
+ self.__shadowImg.setEffect(avg.BlurFXNode(6.0))
+ self.size = self.__aircraftVid.size
+ #self._debug('created')
+
+ @property
+ def alive(self):
+ return self.__alive
+
+ def reset(self):
+ #self._debug('reset')
+ self.active = True
+ self.__alive = True
+ self.__aircraftVid.active = True
+ playVideo(self.__aircraftVid)
+ self.__destroyVid.active = False
+ self.__destroyVid.pause()
+ self.__shadowImg.active = True
+
+ def destroy(self):
+ #self._debug('destroy')
+ self.__alive = False
+ self.__aircraftVid.active = False
+ self.__aircraftVid.pause()
+ self.__destroyVid.active = True
+ playVideo(self.__destroyVid)
+ self.__destroyVid.seekToFrame(0)
+ self.__shadowImg.active = False
+ if player.isUsingGLES():
+ self._hide()
+
+ def _move(self, pos):
+ self.pos = pos
+ self.__shadowImg.pos = self.pos + _Aircraft.__SHADOW_OFFSET
+
+ def _hide(self):
+ #self._debug('hide')
+ self.active = False
+ self.__alive = False
+ self.__aircraftVid.pause()
+ self.__destroyVid.pause()
+ self.__shadowImg.active = False
+
+ @classmethod
+ def _debug(cls, msg):
+ print '%6d [%s] %s' %(player.getFrameTime(), cls.__name__, msg)
+
+
+class PlayerAircraft(_Aircraft):
+ ACTION_KEYS = ('left', 'right', 'up', 'down', 'space')
+ __BULLET_OFFSET_L = avg.Point2D( 52, 16)
+ __BULLET_OFFSET_R = avg.Point2D(140, 16)
+
+ def __init__(self, shadowdiv, gunCtrl, parent=None, **kwargs):
+ super(PlayerAircraft, self).__init__('spitfire', shadowdiv, parent, **kwargs)
+ self.__gunCtrl = gunCtrl
+ self.__bullets = [Bullet(parent=self.parent) for i in xrange(10)]
+ self.__engineSnd = avg.SoundNode(href='flySound.mp3', loop=True, parent=self)
+ self.__bulletSnd = avg.SoundNode(href='bulletSound.mp3', volume=0.75, parent=self)
+ self.__maxX, self.__maxY = self.parent.size - self.size
+
+ def reset(self):
+ super(PlayerAircraft, self).reset()
+ self.__gunCtrl.reset()
+ self._move((self.__maxX / 2, self.__maxY))
+ self.__engineSnd.play()
+
+ def destroy(self):
+ super(PlayerAircraft, self).destroy()
+ self.__engineSnd.stop()
+
+ def update(self, dt, keyStates):
+ d = _Aircraft._SPEED * dt
+ dx = 0
+ if keyStates['left']:
+ dx = -d
+ if keyStates['right']:
+ dx += d
+ dy = 0
+ if keyStates['up']:
+ dy = -d
+ if keyStates['down']:
+ dy += d
+ pos = (max(min(self.x + dx, self.__maxX), 0),
+ max(min(self.y + dy, self.__maxY), 0))
+ if pos != self.pos:
+ self._move(pos)
+
+ if keyStates['space'] and self.__gunCtrl.shoot():
+ # fire bullets
+ bulletLeft = None
+ bulletRight = None
+ for b in self.__bullets:
+ if b.active:
+ b.update(dt)
+ elif not bulletLeft:
+ bulletLeft = b
+ elif not bulletRight:
+ bulletRight = b
+ if not bulletLeft:
+ bulletLeft = Bullet(parent=self.parent)
+ self.__bullets.append(bulletLeft)
+ if not bulletRight:
+ bulletRight = Bullet(parent=self.parent)
+ self.__bullets.append(bulletRight)
+ bulletLeft.reset(self.pos + PlayerAircraft.__BULLET_OFFSET_L)
+ bulletRight.reset(self.pos + PlayerAircraft.__BULLET_OFFSET_R)
+ self.__bulletSnd.play()
+ self.__bulletSnd.seekToTime(0)
+ else:
+ self.__gunCtrl.update(dt)
+ self.updateBullets(dt)
+
+ def updateBullets(self, dt):
+ bulletsAlive = False
+ for b in self.__bullets:
+ if b.active:
+ bulletsAlive = True
+ b.update(dt)
+ return bulletsAlive
+
+ def getActiveBullets(self):
+ return [b for b in self.__bullets if b.active]
+
+
+class EnemyAircraft(_Aircraft):
+ ESCAPED = avg.Publisher.genMessageID()
+
+ def __init__(self, shadowdiv, parent=None, **kwargs):
+ super(EnemyAircraft, self).__init__('enemy', shadowdiv, parent, **kwargs)
+ self.publish(EnemyAircraft.ESCAPED)
+ self.__destroySnd = avg.SoundNode(href='enemyDeath.mp3', volume=2.0, parent=self)
+ self._hide()
+
+ def reset(self):
+ super(EnemyAircraft, self).reset()
+ self._move((randint(0, self.parent.width - self.width), -self.height))
+
+ def destroy(self):
+ super(EnemyAircraft, self).destroy()
+ self.__destroySnd.play()
+ self.__destroySnd.seekToTime(0)
+
+ def update(self, dt):
+ y = self.y + _Aircraft._SPEED * dt
+ if y < self.parent.height:
+ self._move((self.x, y))
+ else:
+ self._hide()
+ self.notifySubscribers(EnemyAircraft.ESCAPED, [])
+
+
+### gui elements ###
+
+class ScrollingBackground(object):
+ __SCROLL_SPEED = 120.0 # px/s
+
+ def __init__(self, parent):
+ self.__imgA = avg.ImageNode(href='ground.jpg', parent=parent)
+ self.__imgB = avg.ImageNode(href='ground.jpg', pos=(0, -self.__imgA.height),
+ parent=parent)
+
+ def update(self, dt):
+ dy = ScrollingBackground.__SCROLL_SPEED * dt
+ self.__imgA.y += dy
+ self.__imgB.y += dy
+ if self.__imgA.y >= self.__imgA.height:
+ self.__imgA.y = self.__imgB.y - self.__imgA.height
+ elif self.__imgB.y >= self.__imgA.height:
+ self.__imgB.y = self.__imgA.y - self.__imgA.height
+
+
+class LiveCounter(avg.DivNode):
+ __NUM_LIVES = 3
+
+ def __init__(self, parent=None, **kwargs):
+ super(LiveCounter, self).__init__(**kwargs)
+ self.registerInstance(self, parent)
+ self.__numLives = 0
+ self.__images = []
+ x = 0
+ for i in xrange(LiveCounter.__NUM_LIVES):
+ avg.ImageNode(href='gui_lives_bg.png', pos=(x, 0), parent=self)
+ img = avg.ImageNode(href='gui_lives_fg.png', pos=(x, 0), parent=self)
+ self.__images.append(img)
+ x += img.width
+
+ def reset(self):
+ self.__numLives = 3
+ for img in self.__images:
+ avg.fadeIn(img, 250)
+
+ def dec(self):
+ assert(self.__numLives)
+ self.__numLives -= 1
+ avg.fadeOut(self.__images[self.__numLives], 250)
+ return not self.__numLives
+
+
+class ScoreCounter(avg.DivNode):
+ def __init__(self, parent=None, **kwargs):
+ super(ScoreCounter, self).__init__(size=(3 * 34, 34), crop=True, **kwargs)
+ self.registerInstance(self, parent)
+ self.__score = 0
+ self.__images = [avg.ImageNode(href='gui_numbers.png', pos=((2 - i) * 34, 0),
+ parent=self) for i in xrange(3)]
+
+ def reset(self):
+ self.__score = 0
+ for img in self.__images:
+ if img.y != 0:
+ avg.LinearAnim(img, 'y', 250, img.y, 0).start()
+
+ def inc(self):
+ self.__score += 1
+ self.__updateImages()
+
+ def dec(self):
+ if self.__score > 0:
+ self.__score -= 1
+ self.__updateImages()
+
+ def __updateImages(self):
+ s = self.__score
+ for img in self.__images:
+ y = s % 10 * -34
+ if img.y != y:
+ avg.LinearAnim(img, 'y', 250, img.y, y).start()
+ s /= 10
+
+
+class GunControl(avg.DivNode):
+ __SHOOT_INTERVAL = 1.0 / 7 # ms
+ __TEMPERATURE_INC = 30 # px/shot
+ __TEMPERATURE_DEC = 60 # px/s
+
+ def __init__(self, parent=None, **kwargs):
+ super(GunControl, self).__init__(**kwargs)
+ self.registerInstance(self, parent)
+ bg = avg.ImageNode(href='gui_heatbar_bg.png', parent=self)
+ self.__heatbar = avg.DivNode(size=(1, bg.height), crop=True, parent=self)
+ avg.ImageNode(href='gui_heatbar_fg.png', parent=self.__heatbar)
+ self.__maxTemp = bg.width - GunControl.__TEMPERATURE_INC
+ self.__shootTimeout = 0.0
+
+ def reset(self):
+ self.__heatbar.width = 1
+
+ def update(self, dt):
+ if self.__shootTimeout > 0.0:
+ self.__shootTimeout = max(0.0, self.__shootTimeout - dt)
+ dw = GunControl.__TEMPERATURE_DEC * dt
+ if self.__heatbar.width > dw:
+ self.__heatbar.width -= dw
+
+ def shoot(self):
+ if self.__shootTimeout == 0.0 and self.__heatbar.width < self.__maxTemp:
+ self.__shootTimeout = GunControl.__SHOOT_INTERVAL
+ self.__heatbar.width += GunControl.__TEMPERATURE_INC
+ return True
+ return False
+
+
+### application ###
+
+class FireBirds(app.MainDiv):
+ ENEMY_SPAWN_TIMEOUT = 1000 # ms
+
+ def onInit(self):
+ self.mediadir = getMediaDir(__file__)
+
+ self.__gameMusic = avg.SoundNode(href='Fire_Birds.mp3', loop=True,
+ volume=0.75, parent=self)
+ self.__scrollingBg = ScrollingBackground(self)
+ self.__shadowDiv = avg.DivNode(parent=self)
+ self.__gameDiv = avg.DivNode(size=self.size, parent=self)
+ self.__guiDiv = avg.DivNode(parent=self)
+
+ bg = avg.ImageNode(href='gui_frame.png', parent=self.__guiDiv)
+ self.__guiDiv.pos = (0, self.height - bg.height)
+ self.__liveCounter = LiveCounter(pos=(8, 12), parent=self.__guiDiv)
+ gunCtrl = GunControl(pos=(300, 54), parent=self.__guiDiv)
+ self.__scoreCounter = ScoreCounter(pos=(1142, 54), parent=self.__guiDiv)
+
+ self.__enemies = []
+ for i in xrange(2):
+ self.__createEnemy()
+ self.__player = PlayerAircraft(self.__shadowDiv, gunCtrl, parent=self.__gameDiv)
+
+ enemyMask = avg.Bitmap(self.mediadir + '/enemy.gif')
+ self.__playerCollisionDetector = collisiondetector.CollisionDetector(
+ enemyMask, avg.Bitmap(self.mediadir + '/spitfire.gif'))
+ self.__bulletCollisionDetector = collisiondetector.CollisionDetector(
+ enemyMask, avg.Bitmap(self.mediadir + '/bullet.gif'))
+
+ self.__keyStates = dict.fromkeys(PlayerAircraft.ACTION_KEYS, False)
+ self.__frameHandlerId = None
+ self.__spawnTimeoutId = None
+ self.__gameMusic.play()
+ self.__start()
+ player.subscribe(player.KEY_DOWN, self.__onKeyDown)
+ player.subscribe(player.KEY_UP, self.__onKeyUp)
+
+ def __onKeyDown(self, event):
+ if self.__player.alive:
+ if event.keystring in PlayerAircraft.ACTION_KEYS:
+ self.__keyStates[event.keystring] = True
+ elif not self.__frameHandlerId: # game stopped
+ if event.keystring == 'space':
+ self.__start()
+ # else: wait for bullets and enemies to leave the screen
+
+ def __onKeyUp(self, event):
+ if event.keystring in PlayerAircraft.ACTION_KEYS:
+ self.__keyStates[event.keystring] = False
+
+ def __start(self):
+ assert(not self.__frameHandlerId and not self.__spawnTimeoutId)
+ self.__liveCounter.reset()
+ self.__scoreCounter.reset()
+ self.__player.reset()
+ self.__frameHandlerId = player.subscribe(player.ON_FRAME, self.__onFrame)
+ self.__spawnTimeoutId = player.setInterval(self.ENEMY_SPAWN_TIMEOUT,
+ self.__spawnEnemy)
+
+ def __stop(self):
+ assert(self.__frameHandlerId and self.__spawnTimeoutId)
+ player.clearInterval(self.__spawnTimeoutId)
+ self.__spawnTimeoutId = None
+
+ def __createEnemy(self):
+ enemy = EnemyAircraft(self.__shadowDiv, parent=self.__gameDiv)
+ enemy.subscribe(EnemyAircraft.ESCAPED, self.__scoreCounter.dec)
+ self.__enemies.append(enemy)
+ return enemy
+
+ def __spawnEnemy(self):
+ assert(self.__frameHandlerId)
+ enemy = None
+ for e in self.__enemies:
+ if not e.active:
+ enemy = e
+ break
+ if not enemy:
+ enemy = self.__createEnemy()
+ enemy.reset()
+
+ def __onFrame(self):
+ dt = player.getFrameDuration() * 0.001
+ self.__scrollingBg.update(dt)
+
+ bullets = self.__player.getActiveBullets()
+ enemiesActive = False
+ for e in self.__enemies:
+ if e.active:
+ enemiesActive = True
+ if e.alive:
+ for b in bullets:
+ if self.__bulletCollisionDetector.detect(e.pos, b.pos):
+ self.__scoreCounter.inc()
+ e.destroy()
+ b.destroy()
+ break
+ if e.alive: # no bullet hit
+ if self.__player.alive and \
+ self.__playerCollisionDetector.detect(e.pos, self.__player.pos):
+ e.destroy()
+ if self.__liveCounter.dec():
+ self.__stop()
+ self.__player.destroy()
+ if e.alive: # no player collision
+ e.update(dt)
+
+ if self.__player.alive:
+ self.__player.update(dt, self.__keyStates)
+ elif not self.__player.updateBullets(dt) and not enemiesActive:
+ # player dead, all bullets and enemies left the screen, all destroy videos played
+ player.unsubscribe(player.ON_FRAME, self.__frameHandlerId)
+ self.__frameHandlerId = None
+
+
+if __name__ == '__main__':
+ app.App().run(FireBirds(), app_resolution='1280x720')
+
diff --git a/src/samples/firebirds/media/Fire_Birds.mp3 b/src/samples/firebirds/media/Fire_Birds.mp3
new file mode 100644
index 0000000..264723e
--- /dev/null
+++ b/src/samples/firebirds/media/Fire_Birds.mp3
Binary files differ
diff --git a/src/samples/firebirds/media/Makefile.am b/src/samples/firebirds/media/Makefile.am
new file mode 100644
index 0000000..bfd5cdf
--- /dev/null
+++ b/src/samples/firebirds/media/Makefile.am
@@ -0,0 +1,5 @@
+EXTRA_DIST = $(wildcard *.gif) $(wildcard *.png) $(wildcard *.jpg) \
+ $(wildcard *.mov) $(wildcard *.mp3)
+datadir = $(pkgpyexecdir)/samples/firebirds/media
+data_DATA = $(wildcard *.gif) $(wildcard *.png) $(wildcard *.jpg) \
+ $(wildcard *.mov) $(wildcard *.mp3)
diff --git a/src/samples/firebirds/media/bullet.gif b/src/samples/firebirds/media/bullet.gif
new file mode 100644
index 0000000..ad1cca3
--- /dev/null
+++ b/src/samples/firebirds/media/bullet.gif
Binary files differ
diff --git a/src/samples/firebirds/media/bullet.mov b/src/samples/firebirds/media/bullet.mov
new file mode 100644
index 0000000..eac58d5
--- /dev/null
+++ b/src/samples/firebirds/media/bullet.mov
Binary files differ
diff --git a/src/samples/firebirds/media/bulletSound.mp3 b/src/samples/firebirds/media/bulletSound.mp3
new file mode 100644
index 0000000..2172667
--- /dev/null
+++ b/src/samples/firebirds/media/bulletSound.mp3
Binary files differ
diff --git a/src/samples/firebirds/media/enemy.gif b/src/samples/firebirds/media/enemy.gif
new file mode 100644
index 0000000..59cc1e2
--- /dev/null
+++ b/src/samples/firebirds/media/enemy.gif
Binary files differ
diff --git a/src/samples/firebirds/media/enemy.mov b/src/samples/firebirds/media/enemy.mov
new file mode 100644
index 0000000..8487095
--- /dev/null
+++ b/src/samples/firebirds/media/enemy.mov
Binary files differ
diff --git a/src/samples/firebirds/media/enemyDeath.mp3 b/src/samples/firebirds/media/enemyDeath.mp3
new file mode 100644
index 0000000..c5b0b67
--- /dev/null
+++ b/src/samples/firebirds/media/enemyDeath.mp3
Binary files differ
diff --git a/src/samples/firebirds/media/explosion.mov b/src/samples/firebirds/media/explosion.mov
new file mode 100644
index 0000000..a03f4e9
--- /dev/null
+++ b/src/samples/firebirds/media/explosion.mov
Binary files differ
diff --git a/src/samples/firebirds/media/flySound.mp3 b/src/samples/firebirds/media/flySound.mp3
new file mode 100644
index 0000000..bc83bf4
--- /dev/null
+++ b/src/samples/firebirds/media/flySound.mp3
Binary files differ
diff --git a/src/samples/firebirds/media/ground.jpg b/src/samples/firebirds/media/ground.jpg
new file mode 100644
index 0000000..2425fcc
--- /dev/null
+++ b/src/samples/firebirds/media/ground.jpg
Binary files differ
diff --git a/src/samples/firebirds/media/gui_frame.png b/src/samples/firebirds/media/gui_frame.png
new file mode 100644
index 0000000..414cb00
--- /dev/null
+++ b/src/samples/firebirds/media/gui_frame.png
Binary files differ
diff --git a/src/samples/firebirds/media/gui_heatbar_bg.png b/src/samples/firebirds/media/gui_heatbar_bg.png
new file mode 100644
index 0000000..3e330e2
--- /dev/null
+++ b/src/samples/firebirds/media/gui_heatbar_bg.png
Binary files differ
diff --git a/src/samples/firebirds/media/gui_heatbar_fg.png b/src/samples/firebirds/media/gui_heatbar_fg.png
new file mode 100644
index 0000000..fa79bb7
--- /dev/null
+++ b/src/samples/firebirds/media/gui_heatbar_fg.png
Binary files differ
diff --git a/src/samples/firebirds/media/gui_lives_bg.png b/src/samples/firebirds/media/gui_lives_bg.png
new file mode 100644
index 0000000..e206a9d
--- /dev/null
+++ b/src/samples/firebirds/media/gui_lives_bg.png
Binary files differ
diff --git a/src/samples/firebirds/media/gui_lives_fg.png b/src/samples/firebirds/media/gui_lives_fg.png
new file mode 100644
index 0000000..cdceba8
--- /dev/null
+++ b/src/samples/firebirds/media/gui_lives_fg.png
Binary files differ
diff --git a/src/samples/firebirds/media/gui_numbers.png b/src/samples/firebirds/media/gui_numbers.png
new file mode 100644
index 0000000..c567766
--- /dev/null
+++ b/src/samples/firebirds/media/gui_numbers.png
Binary files differ
diff --git a/src/samples/firebirds/media/spitfire.gif b/src/samples/firebirds/media/spitfire.gif
new file mode 100644
index 0000000..47976cc
--- /dev/null
+++ b/src/samples/firebirds/media/spitfire.gif
Binary files differ
diff --git a/src/samples/firebirds/media/spitfire.mov b/src/samples/firebirds/media/spitfire.mov
new file mode 100644
index 0000000..384cac2
--- /dev/null
+++ b/src/samples/firebirds/media/spitfire.mov
Binary files differ
diff --git a/src/samples/firebirds/plugin/CollisionDetector.cpp b/src/samples/firebirds/plugin/CollisionDetector.cpp
new file mode 100644
index 0000000..1eca5c9
--- /dev/null
+++ b/src/samples/firebirds/plugin/CollisionDetector.cpp
@@ -0,0 +1,122 @@
+#include "CollisionDetector.h"
+
+#include "../../../base/ScopeTimer.h"
+#include "../../../wrapper/WrapHelper.h"
+
+namespace avg {
+
+CollisionDetector::CollisionDetector(const Bitmap& bmpA, const Bitmap& bmpB)
+{
+ m_pBmpA = new Bitmap(bmpA.getSize(), B8G8R8A8);
+ m_pBmpA->copyPixels(bmpA);
+ m_pBmpB = new Bitmap(bmpB.getSize(), B8G8R8A8);
+ m_pBmpB->copyPixels(bmpB);
+}
+
+CollisionDetector::~CollisionDetector()
+{
+ delete m_pBmpA;
+ delete m_pBmpB;
+}
+
+static ProfilingZoneID CollisionDetectorProfilingZone("Detect collisions");
+
+bool CollisionDetector::detect(glm::vec2 posA, glm::vec2 posB)
+{
+ ScopeTimer Timer(CollisionDetectorProfilingZone);
+
+ int widthA = m_pBmpA->getSize().x;
+ int heightA = m_pBmpA->getSize().y;
+ int rightA = posA.x + widthA;
+ int bottomA = posA.y + heightA;
+ int widthB = m_pBmpB->getSize().x;
+ int heightB = m_pBmpB->getSize().y;
+ int rightB = posB.x + widthB;
+ int bottomB = posB.y + heightB;
+
+ // bounding box test
+ if (rightA <= posB.x || posA.x >= rightB || bottomA <= posB.y || posA.y >= bottomB) {
+ return false;
+ }
+
+ // pixel level test
+
+ // calculate x overlap
+ int dX = posB.x - posA.x;
+ if (dX < 0) {
+ posA.x = 0;
+ posB.x = -dX;
+ }
+ else {
+ posA.x = dX;
+ posB.x = 0;
+ }
+ int width;
+ dX = rightB - rightA;
+ if (dX < 0)
+ width = std::min(widthA + dX, widthB);
+ else
+ width = std::min(widthB - dX, widthA);
+ // calculate y overlap
+ int dY = posB.y - posA.y;
+ if (dY < 0) {
+ posA.y = 0;
+ posB.y = -dY;
+ }
+ else {
+ posA.y = dY;
+ posB.y = 0;
+ }
+ int height;
+ dY = bottomB - bottomA;
+ if (dY < 0)
+ height = std::min(heightA + dY, heightB);
+ else
+ height = std::min(heightB - dY, heightA);
+
+ // test alpha channels
+ const unsigned char* pPixStartA = m_pBmpA->getPixels() +
+ (int) posA.y * m_pBmpA->getStride() +
+ (int) posA.x * 4 + 3; // alpha channel of 1st A pixel
+ const unsigned char* pPixStartB = m_pBmpB->getPixels() +
+ (int) posB.y * m_pBmpB->getStride() +
+ (int) posB.x * 4 + 3; // alpha channel of 1st B pixel
+ const unsigned char* pPixA = pPixStartA;
+ const unsigned char* pPixB = pPixStartB;
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ if (*pPixA && *pPixB) {
+ return true; // both pixels have alpha > 0 --> collision
+ }
+ pPixA += 4;
+ pPixB += 4;
+ }
+ pPixA = pPixStartA + y * m_pBmpA->getStride();
+ pPixB = pPixStartB + y * m_pBmpB->getStride();
+ }
+
+ return false;
+}
+
+} // namespace avg
+
+
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(collisiondetector)
+{
+ class_<avg::CollisionDetector, boost::noncopyable>("CollisionDetector", no_init)
+ .def(init<avg::Bitmap&, avg::Bitmap&>())
+ .def("detect", &avg::CollisionDetector::detect)
+ ;
+}
+
+
+AVG_PLUGIN_API void registerPlugin()
+{
+ initcollisiondetector(); // created by BOOST_PYTHON_MODULE
+ object mainModule(handle<>(borrowed(PyImport_AddModule("__main__"))));
+ object collisiondetectorModule(handle<>(PyImport_ImportModule("collisiondetector")));
+ mainModule.attr("collisiondetector") = collisiondetectorModule;
+}
+
diff --git a/src/samples/firebirds/plugin/CollisionDetector.h b/src/samples/firebirds/plugin/CollisionDetector.h
new file mode 100644
index 0000000..7d477e2
--- /dev/null
+++ b/src/samples/firebirds/plugin/CollisionDetector.h
@@ -0,0 +1,28 @@
+#ifndef _COLLISION_DETECTOR_H_
+#define _COLLISION_DETECTOR_H_
+
+#define AVG_PLUGIN
+
+#include "../../../graphics/Bitmap.h"
+
+
+namespace avg {
+
+class CollisionDetector
+{
+public:
+ CollisionDetector(const Bitmap& bmpA, const Bitmap& bmpB);
+ ~CollisionDetector();
+
+ bool detect(glm::vec2 posA, glm::vec2 posB);
+
+private:
+ Bitmap* m_pBmpA;
+ Bitmap* m_pBmpB;
+};
+
+}
+
+
+#endif
+
diff --git a/src/samples/firebirds/plugin/Makefile.am b/src/samples/firebirds/plugin/Makefile.am
new file mode 100644
index 0000000..69a63db
--- /dev/null
+++ b/src/samples/firebirds/plugin/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = -I. @XML2_CFLAGS@ @PYTHON_CPPFLAGS@
+
+if APPLE
+ XGL_LIBS =
+ EXTRA_LDFLAGS = -read_only_relocs suppress
+else
+ XGL_LIBS = -lXxf86vm
+ EXTRA_LDFLAGS = -XCClinker ../../../wrapper/.libs/avg.so
+endif
+
+ALL_GL_LIBS = @GL_LIBS@ @SDL_LIBS@ $(XGL_LIBS)
+
+pkgplugindir = $(pkgpyexecdir)/samples/firebirds/plugin
+pkgplugin_LTLIBRARIES = collisiondetector.la
+collisiondetector_la_SOURCES = CollisionDetector.h CollisionDetector.cpp
+collisiondetector_la_LDFLAGS = $(EXTRA_LDFLAGS) -module
diff --git a/src/samples/flashmessages.py b/src/samples/flashmessages.py
new file mode 100644
index 0000000..25c11d1
--- /dev/null
+++ b/src/samples/flashmessages.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# libavg - Media Playback Engine.
+# Copyright (C) 2003-2014 Ulrich von Zadow
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Current versions can be found at www.libavg.de
+#
+# Original author of this file is OXullo Interecans <x at brainrapers dot org>
+# Sponsored by Archimedes Exhibitions GmbH ( http://www.archimedes-exhibitions.de )
+
+
+import libavg
+from libavg import app
+
+
+class MyScene(app.MainDiv):
+ def onInit(self):
+ # This message is displayed immediately
+ app.flashmessage.FlashMessage('helloworld! this message will disappear in a bit')
+
+ # Displayed when the 'v' key is pressed, again a simple flash message
+ app.keyboardmanager.bindKeyDown('v',
+ lambda: app.flashmessage.FlashMessage('v key pressed'), 'Test me')
+
+ # This message shows the message in a different color and sends the text to
+ # the logger as well
+ app.keyboardmanager.bindKeyDown('b',
+ lambda: app.flashmessage.FlashMessage('this is an error', isError=True),
+ 'Test me too')
+
+ # This message disappears when it's acknowledged with a mouse click
+ app.keyboardmanager.bindKeyDown('n',
+ lambda: app.flashmessage.FlashMessage('persistent, click here to dismiss',
+ acknowledge=True),
+ 'Test me too again')
+
+ libavg.avg.WordsNode(parent=self, pos=(10, 50), fontsize=20,
+ text='Press the keys: v, b, n')
+
+
+if __name__ == '__main__':
+ app.App().run(MyScene())
+
diff --git a/src/samples/fontstyle.py b/src/samples/fontstyle.py
new file mode 100755
index 0000000..c6707a4
--- /dev/null
+++ b/src/samples/fontstyle.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+BASE_STYLE = avg.FontStyle(font='Arial', variant='Regular', fontsize=14, linespacing=2)
+HEADER_STYLE = avg.FontStyle(basestyle=BASE_STYLE, variant='Bold', color='FF0000')
+
+SAMPLE_TEXT="""
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vitae gravida urna. Nam ut nisi ac nulla venenatis tincidunt a in urna. Cras vel enim purus, sit amet adipiscing dolor. Aliquam tincidunt interdum velit sed hendrerit. Proin ut enim dolor, sit amet egestas mi. Aenean felis quam, sollicitudin sed tempus in, pharetra eget turpis.
+"""
+
+canvas = player.createMainCanvas(size=(640, 480))
+rootNode = canvas.getRootNode()
+
+avg.WordsNode(pos=(50, 50), text='Lorem Ipsum', fontstyle=HEADER_STYLE, parent=rootNode)
+avg.WordsNode(pos=(50, 70), text='Lorem Ipsum', fontstyle=HEADER_STYLE, variant='Italic',
+ parent=rootNode)
+avg.WordsNode(pos=(50, 90), text=SAMPLE_TEXT, width=400, fontstyle=BASE_STYLE,
+ parent=rootNode)
+
+player.play()
+
diff --git a/src/samples/gestures.py b/src/samples/gestures.py
new file mode 100755
index 0000000..9b4a0be
--- /dev/null
+++ b/src/samples/gestures.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, gesture, app
+
+RESOLUTION = avg.Point2D(800, 600)
+
+def moveNodeToTop(node):
+ parent = node.getParent()
+ parent.reorderChild(node, parent.getNumChildren()-1)
+
+def moveNodeOnScreen(node):
+ center = node.pos + node.size/2
+ if center.x < 0:
+ node.pos = (-node.size.x/2, node.pos.y)
+ if center.x > RESOLUTION.x:
+ node.pos = (RESOLUTION.x-node.size.x/2, node.pos.y)
+ if center.y < 0:
+ node.pos = (node.pos.x, -node.size.y/2)
+ if center.y > RESOLUTION.y:
+ node.pos = (node.pos.x, RESOLUTION.y-node.size.y/2)
+
+
+class TextRect(avg.DivNode):
+ def __init__(self, text, parent=None, **kwargs):
+ super(TextRect, self).__init__(size=(150,40), **kwargs)
+ if parent:
+ parent.appendChild(self)
+
+ self.rect = avg.RectNode(size=self.size, fillopacity=1, fillcolor="000000",
+ color="FFFFFF", parent=self)
+ self.words = avg.WordsNode(color="FFFFFF", text=text, alignment="center",
+ parent=self)
+ self.words.pos = (self.size-(0,self.words.size.y)) / 2
+
+ def getSize(self):
+ return self.__divSize
+
+ def setSize(self, size):
+ self.rect.size = size
+ self.words.pos = (size-(0,self.words.size.y)) / 2
+ self.__divSize = size
+ __divSize = avg.DivNode.size
+ size = property(getSize, setSize)
+
+
+class TransformNode(TextRect):
+ def __init__(self, text, ignoreScale, ignoreRotation, friction=-1, **kwargs):
+ super(TransformNode, self).__init__(text, **kwargs)
+ self.__ignoreScale = ignoreScale
+ self.__ignoreRotation = ignoreRotation
+
+ self.recognizer = gesture.TransformRecognizer(
+ eventNode=self,
+ detectedHandler=self.__onDetected,
+ moveHandler=self.__onMove,
+ upHandler=self.__onUp,
+ friction=friction
+ )
+
+ def __onDetected(self):
+ moveNodeToTop(self)
+
+ def __onMove(self, transform):
+ if self.__ignoreScale:
+ transform.scale = 1
+ if self.__ignoreRotation:
+ transform.rot = 0
+ transform.moveNode(self)
+ moveNodeOnScreen(self)
+
+ def __onUp(self, transform):
+ pass
+
+
+class TransformChildNode(avg.DivNode):
+ def __init__(self, text, parent=None, **kwargs):
+ super(TransformChildNode, self).__init__( **kwargs)
+ if parent:
+ parent.appendChild(self)
+
+ self.textRect = TextRect(text, parent=self)
+ self.size = self.textRect.size
+
+ self.inputNode = avg.RectNode(size=(self.size.x, self.size.y/2),
+ fillopacity=0.5, fillcolor="808080", strokewidth=0, parent=self)
+ self.recognizer = gesture.TransformRecognizer(
+ eventNode=self.inputNode,
+ coordSysNode=self,
+ detectedHandler=self.__onDetected,
+ moveHandler=self.__onMove,
+ friction=0.05
+ )
+
+ def __onDetected(self):
+ moveNodeToTop(self)
+
+ def __onMove(self, transform):
+ transform.moveNode(self)
+ moveNodeOnScreen(self)
+ self.textRect.size = self.size
+ self.inputNode.size = (self.size.x, self.size.y/2)
+
+
+class DragNode(TextRect):
+ def __init__(self, text, friction=-1, **kwargs):
+ super(DragNode, self).__init__(text, **kwargs)
+
+ self.recognizer = gesture.DragRecognizer(
+ eventNode=self,
+ detectedHandler=self.__onDetected,
+ moveHandler=self.__onMove,
+ upHandler=self.__onMove,
+ endHandler=self.__onEnd,
+ friction=friction
+ )
+
+ def __onDetected(self):
+ self.__dragStartPos = self.pos
+ moveNodeToTop(self)
+
+ def __onMove(self, offset):
+ self.pos = self.__dragStartPos + offset
+ moveNodeOnScreen(self)
+
+ def __onEnd(self):
+ pass
+
+
+class ConstrainedDragNode(TextRect):
+ def __init__(self, text, friction=-1, **kwargs):
+ super(ConstrainedDragNode, self).__init__(text, **kwargs)
+
+ self.recognizer = gesture.DragRecognizer(
+ eventNode=self,
+ detectedHandler=self.__onDetected,
+ moveHandler=self.__onHorizMove,
+ upHandler=self.__onHorizMove,
+ direction=gesture.DragRecognizer.HORIZONTAL,
+ friction=0.05
+ )
+
+ self.recognizer2 = gesture.DragRecognizer(
+ eventNode=self,
+ detectedHandler=self.__onDetected,
+ moveHandler=self.__onVertMove,
+ upHandler=self.__onVertMove,
+ direction=gesture.DragRecognizer.VERTICAL,
+ friction=0.05
+ )
+
+ def __onDetected(self):
+ self.__dragStartPos = self.pos
+ moveNodeToTop(self)
+
+ def __onHorizMove(self, offset):
+ self.pos = self.__dragStartPos + (offset.x, 0)
+ moveNodeOnScreen(self)
+
+ def __onVertMove(self, offset):
+ self.pos = self.__dragStartPos + (0, offset.y)
+ moveNodeOnScreen(self)
+
+
+class TapNode(TextRect):
+ def __init__(self, text, isDoubleTap, **kwargs):
+ super(TapNode, self).__init__(text, **kwargs)
+
+ if isDoubleTap:
+ self.recognizer = gesture.DoubletapRecognizer(node=self,
+ possibleHandler=self.__onPossible, detectedHandler=self.__onDetected,
+ failHandler=self.__onFail)
+ else:
+ self.recognizer = gesture.TapRecognizer(node=self,
+ possibleHandler=self.__onPossible, detectedHandler=self.__onDetected,
+ failHandler=self.__onFail)
+
+ def __onPossible(self):
+ self.rect.fillcolor = "FFFFFF"
+ self.words.color = "000000"
+
+ def __onDetected(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "00FF00"
+
+ def __onFail(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "FF0000"
+
+
+class SwipeNode(TextRect):
+ def __init__(self, text, numContacts, **kwargs):
+ super(SwipeNode, self).__init__(text, **kwargs)
+
+ self.recognizer = gesture.SwipeRecognizer(node=self, minDist=25,
+ numContacts=numContacts, direction=gesture.SwipeRecognizer.RIGHT,
+ possibleHandler=self.__onPossible, detectedHandler=self.__onDetected,
+ failHandler=self.__onFail)
+
+ def __onPossible(self):
+ self.rect.fillcolor = "FFFFFF"
+ self.words.color = "000000"
+
+ def __onDetected(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "00FF00"
+
+ def __onFail(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "FF0000"
+
+
+class HoldNode(TextRect):
+ def __init__(self, text, **kwargs):
+ super(HoldNode, self).__init__(text, **kwargs)
+
+ self.recognizer = gesture.HoldRecognizer(node=self,
+ possibleHandler=self.__onPossible, detectedHandler=self.__onDetected,
+ failHandler=self.__onFail, stopHandler=self.__onStop)
+
+ def __onPossible(self):
+ self.rect.fillcolor = "FFFFFF"
+ self.rect.color = "FFFFFF"
+ self.words.color = "000000"
+
+ def __onDetected(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "00FF00"
+
+ def __onFail(self):
+ self.rect.fillcolor = "000000"
+ self.words.color = "FFFFFF"
+ self.rect.color = "FF0000"
+
+ def __onStop(self):
+ self.rect.fillcolor = "000000"
+ self.rect.color = "FFFFFF"
+ self.words.color = "FFFFFF"
+
+
+class GestureDemoDiv(app.MainDiv):
+
+ def onInit(self):
+ TransformNode(text="TransformRecognizer",
+ ignoreRotation=False, ignoreScale=False, pos=(20,20), parent=self)
+
+ TransformNode(text="TransformRecognizer<br/>ignoreRotation",
+ ignoreRotation=True, ignoreScale=False, pos=(20,70), parent=self)
+
+ TransformNode(text="TransformRecognizer<br/>ignoreScale",
+ ignoreRotation=False, ignoreScale=True, pos=(20,120), parent=self)
+
+ TransformNode(text="TransformRecognizer<br/>friction",
+ ignoreRotation=False, ignoreScale=False,
+ pos=(20,170), friction=0.02, parent=self)
+
+ TransformChildNode(text="TransformRecognizer<br/>child dragger",
+ pos=(20,220), parent=self)
+
+ DragNode(text="DragRecognizer", pos=(200,20), parent=self)
+
+ DragNode(text="DragRecognizer<br/>friction", pos=(200,70), friction=0.01,
+ parent=self)
+
+ ConstrainedDragNode(text="DragRecognizer<br/>constrained", pos=(200,120),
+ friction=0.01, parent=self)
+
+ TapNode(text="TapRecognizer", pos=(380,20), isDoubleTap=False, parent=self)
+
+ TapNode(text="DoubletapRecognizer", pos=(380,70), isDoubleTap=True, parent=self)
+
+ HoldNode(text="HoldRecognizer", pos=(380,120), parent=self)
+
+ SwipeNode(text="SwipeRecognizer<br/>(Right)", pos=(380,170),
+ numContacts=1, parent=self)
+
+ SwipeNode(text="SwipeRecognizer<br/>(Right, 2 fingers)", pos=(380,220),
+ numContacts=2, parent=self)
+
+
+if __name__ == '__main__':
+ app.App().run(GestureDemoDiv(), app_resolution="800,600")
diff --git a/src/samples/globalcoords.py b/src/samples/globalcoords.py
new file mode 100755
index 0000000..be95bb2
--- /dev/null
+++ b/src/samples/globalcoords.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+avg.ImageNode(pos=(40,30), size=(80,60), href="rgb24-64x64.png", parent=rootNode)
+player.play()
diff --git a/src/samples/invertfx.py b/src/samples/invertfx.py
new file mode 100755
index 0000000..039a99a
--- /dev/null
+++ b/src/samples/invertfx.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# libavg - Media Playback Engine.
+# Copyright (C) 2003-2014 Ulrich von Zadow
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Current versions can be found at www.libavg.de
+
+from libavg import avg, app
+
+class Invert(app.MainDiv):
+ def onInit(self):
+ orig = avg.ImageNode(parent=self, href='../test/media/hsl.png')
+ invert = avg.ImageNode(parent=self, href='../test/media/hsl.png',
+ pos=(orig.size.x+10, 0))
+ invert.setEffect(avg.InvertFXNode())
+
+
+if __name__ == '__main__':
+ app.App().run(Invert(), app_resolution='200x200')
+
diff --git a/src/samples/localcoords.py b/src/samples/localcoords.py
new file mode 100755
index 0000000..f40b63f
--- /dev/null
+++ b/src/samples/localcoords.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+divNode = avg.DivNode(pos=(40,30), parent=rootNode)
+avg.ImageNode(pos=(40,30), size=(80,60), href="rgb24-64x64.png", parent=divNode)
+player.play()
diff --git a/src/samples/localcoordsrot.py b/src/samples/localcoordsrot.py
new file mode 100755
index 0000000..0cefadd
--- /dev/null
+++ b/src/samples/localcoordsrot.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+divNode = avg.DivNode(pos=(120,30), pivot=(0,0), angle=1.570, parent=rootNode)
+avg.ImageNode(pos=(40,30), size=(40,30), href="rgb24-64x64.png", parent=divNode)
+player.play()
+
diff --git a/src/samples/logsample.py b/src/samples/logsample.py
new file mode 100755
index 0000000..0436c4f
--- /dev/null
+++ b/src/samples/logsample.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import logging
+
+from libavg import avg, app
+
+# Setup Python Logger
+hdlr = logging.StreamHandler()
+# category is added as an extra formatting key by libavg
+formatter = logging.Formatter('[%(asctime)s][%(levelname)s][%(category)s] : %(message)s')
+hdlr.setFormatter(formatter)
+pyLogger = logging.getLogger(__name__)
+pyLogger.addHandler(hdlr)
+pyLogger.propagate = False
+pyLogger.level = logging.DEBUG
+
+
+class LoggingTest(app.MainDiv):
+ def onInit(self):
+ # Add the python logger to libavgs logger as a message sink
+ avg.logger.removeStdLogSink()
+ avg.logger.addSink(pyLogger)
+
+ avg.logger.debug("Hidden, unless AVG_LOG_CATEGORIES configured with APP:DEBUG")
+
+ avg.logger.configureCategory(avg.logger.Category.APP, avg.logger.Severity.INFO)
+ avg.logger.log("Custom Info level message", avg.logger.Category.APP,
+ avg.logger.Severity.INFO)
+
+ avg.logger.info("Info level message, with APP Category")
+ avg.logger.warning("Warn level message, with APP Category")
+
+ #Remove the logSink, no message should be logged now, if run with
+ #AVG_LOG_OMIT_STDERR=1
+ #avg.logger.removeSink(logging.getLogger("MY_APP"))
+
+ avg.logger.error("std::err - Error")
+ avg.logger.critical("std::err - Critical")
+ avg.logger.log("std::err - Log")
+
+ #Register custom log category
+ CUSTOM_LOG_CAT = avg.logger.configureCategory("My Custom Category",
+ avg.logger.Severity.INFO)
+
+ #Log with custom log category
+ avg.logger.log("Message with custom category", CUSTOM_LOG_CAT)
+ avg.logger.debug("Hidden message", CUSTOM_LOG_CAT)
+ avg.logger.configureCategory(CUSTOM_LOG_CAT, avg.logger.Severity.DBG)
+ avg.logger.debug("This will show up", CUSTOM_LOG_CAT)
+
+
+if __name__ == '__main__':
+ app.App().run(LoggingTest(), app_resolution='140x140')
+
diff --git a/src/samples/mesh.py b/src/samples/mesh.py
new file mode 100755
index 0000000..8f18de1
--- /dev/null
+++ b/src/samples/mesh.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+avg.MeshNode(texhref="rgb24-64x64.png",
+ vertexcoords=((0,0), (64,0), (0,64), (64, 64), (32, 32)),
+ texcoords=((0,0), (1,0), (0,1), (1,1), (0.5,0.5)),
+ triangles=((0,1,4), (1,3,4), (3,2,4), (2,0,4)),
+ parent=player.getRootNode())
+player.play()
+
diff --git a/src/samples/minimal.py b/src/samples/minimal.py
new file mode 100755
index 0000000..bc57f21
--- /dev/null
+++ b/src/samples/minimal.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+player.play()
diff --git a/src/samples/mpeg1-48x48-sound.avi b/src/samples/mpeg1-48x48-sound.avi
new file mode 100644
index 0000000..be415db
--- /dev/null
+++ b/src/samples/mpeg1-48x48-sound.avi
Binary files differ
diff --git a/src/samples/plugin.py b/src/samples/plugin.py
new file mode 100755
index 0000000..6aa7100
--- /dev/null
+++ b/src/samples/plugin.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import player
+
+canvas = player.createMainCanvas(size=(160,120))
+# Change following line if the plugin is somewhere else.
+player.pluginPath = "../test/plugin/.libs"
+player.loadPlugin("colorplugin")
+
+rootNode = canvas.getRootNode()
+node = colorplugin.ColorNode(fillcolor="7f7f00", parent=rootNode)
+node.fillcolor = "7f007f"
+player.play()
+
diff --git a/src/samples/rgb24-64x64.png b/src/samples/rgb24-64x64.png
new file mode 100644
index 0000000..cca71fe
--- /dev/null
+++ b/src/samples/rgb24-64x64.png
Binary files differ
diff --git a/src/samples/rotcustompivot.py b/src/samples/rotcustompivot.py
new file mode 100755
index 0000000..b4765a6
--- /dev/null
+++ b/src/samples/rotcustompivot.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+avg.ImageNode(pos=(80,30), size=(40,30), href="rgb24-64x64.png", angle=1.570, pivot=(0,0),
+ parent=rootNode)
+player.play()
+
diff --git a/src/samples/rotdefaultpivot.py b/src/samples/rotdefaultpivot.py
new file mode 100755
index 0000000..99f1826
--- /dev/null
+++ b/src/samples/rotdefaultpivot.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+avg.ImageNode(pos=(40,30), size=(80,60), href="rgb24-64x64.png", angle=1.570,
+ parent=rootNode)
+player.play()
+
diff --git a/src/samples/showvideo.py b/src/samples/showvideo.py
new file mode 100755
index 0000000..571034b
--- /dev/null
+++ b/src/samples/showvideo.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, app
+import sys
+
+class VideoPlayer(app.MainDiv):
+ def init(self):
+ self.videoNode = avg.VideoNode(
+ href=sys.argv[1],
+ parent=self)
+ self.videoNode.play()
+
+app.App().run(VideoPlayer(), app_resolution='1920x1080', app_window_size='720x450')
diff --git a/src/samples/slideshow.py b/src/samples/slideshow.py
new file mode 100755
index 0000000..98704d0
--- /dev/null
+++ b/src/samples/slideshow.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# libavg - Media Playback Engine.
+# Copyright (C) 2003-2014 Ulrich von Zadow
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Current versions can be found at www.libavg.de
+#
+# Original author of this file: Thomas Schott <scotty@c-base.org>
+#
+
+"""
+Image slideshow example which shows all images found in the current working
+directory (default) or the one provided via the "app_image_dir" setting.
+
+Images are cross-faded and some random motion/scaling is applied while they're shown.
+This example also shows how to use libavg's BitmapManager to asynchronously load images
+in background.
+"""
+
+# TODO:
+# add app settings for:
+# * show/transition intervals
+# * max. move distance
+# * sorted/shuffled show order (shuffled yet)
+
+import sys
+import os
+from random import shuffle, randint
+from libavg import avg, player, app
+
+
+IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tga', '.tif', '.tiff']
+SHOW_INTERVAL = 6000 # [ms]
+TRANS_INTERVAL = 2000 # [ms]
+CHANGE_INTERVAL = SHOW_INTERVAL + TRANS_INTERVAL
+ANIM_INTERVAL = CHANGE_INTERVAL + TRANS_INTERVAL
+ANIM_MAX_MOVE = 200 # [px]
+
+BitmapMgr = avg.BitmapManager.get()
+
+
+def scaleMax(srcSize, maxSize):
+ """
+ Returns scrSize aspect correct scaled to fit right into maxSize.
+ """
+ aspect = srcSize.x / srcSize.y
+ if aspect < maxSize.x / maxSize.y:
+ return avg.Point2D(maxSize.y * aspect, maxSize.y)
+ return avg.Point2D(maxSize.x, maxSize.x / aspect)
+
+def scaleMin(srcSize, minSize):
+ """
+ Returns scrSize aspect correct scaled to completely fill minSize.
+ """
+ aspect = srcSize.x / srcSize.y
+ if aspect < minSize.x / minSize.y:
+ return avg.Point2D(minSize.x, minSize.x / aspect)
+ return avg.Point2D(minSize.y * aspect, minSize.y)
+
+
+class Slide(avg.ImageNode):
+ HIDE_DONE = avg.Publisher.genMessageID()
+
+ def __init__(self, parent=None, **kwargs):
+ super(Slide, self).__init__(opacity=0.0, **kwargs)
+ self.registerInstance(self, parent)
+ self.publish(Slide.HIDE_DONE)
+
+ def show(self):
+ s = self.getMediaSize()
+ assert s.x and s.y
+ # initial size and position (scaled to screen size and centered)
+ self.size = scaleMax(s, self.parent.size)
+ self.pos = (self.parent.size - self.size) * 0.5
+ # random final size and position (center moved by (dx, dy) and scaled up accordingly)
+ dx = float(randint(-ANIM_MAX_MOVE, ANIM_MAX_MOVE))
+ dy = float(randint(-ANIM_MAX_MOVE, ANIM_MAX_MOVE))
+ size = scaleMin(s, self.size + avg.Point2D(abs(dx), abs(dy)) * 2.0)
+ pos = self.pos + avg.Point2D(dx, dy) + (self.size - size) * 0.5
+ # start in-transition
+ avg.fadeIn(self, TRANS_INTERVAL)
+ # start move/scale animation
+ avg.ParallelAnim([
+ avg.LinearAnim(self, 'size', ANIM_INTERVAL, self.size, size),
+ avg.LinearAnim(self, 'pos', ANIM_INTERVAL, self.pos, pos)]).start()
+
+ def hide(self):
+ # start out-transition, notify subscribers when finished
+ avg.fadeOut(self, TRANS_INTERVAL,
+ lambda: self.notifySubscribers(Slide.HIDE_DONE, [self]))
+
+
+class Slideshow(app.MainDiv):
+ def onArgvParserCreated(self, parser):
+ parser.set_usage('%prog <images dir>')
+
+ def onArgvParsed(self, options, args, parser):
+ if len(args) != 1:
+ parser.print_help()
+ sys.exit(1)
+ self._imagesDir = args[0]
+
+ def onInit(self):
+ if not os.path.isdir(self._imagesDir):
+ avg.logger.error('Directory [%s] not found' % self._imagesDir)
+ exit(1)
+ avg.logger.info('Scanning directory [%s] ...' % self._imagesDir)
+
+ imgExts = tuple(IMAGE_EXTENSIONS + [ext.upper() for ext in IMAGE_EXTENSIONS])
+ self.__imgFiles = [os.path.join(self._imagesDir, imgFile) for imgFile in
+ filter(lambda f: f.endswith(imgExts), os.listdir(self._imagesDir))]
+ if not self.__imgFiles:
+ avg.logger.error('No image files found, '
+ 'scanned file extensions:\n%s' % (', '.join(imgExts)))
+ exit(1)
+ l = len(self.__imgFiles)
+ avg.logger.info('%d image file%s found' % (l, 's' if l > 1 else ''))
+ shuffle(self.__imgFiles)
+
+ self.__slidesDiv = avg.DivNode(size=self.size, parent=self)
+ # ping-pong two slides for cross-fade transition
+ self.__newSlide = Slide(parent=self.__slidesDiv)
+ self.__oldSlide = Slide(href=self.__imgFiles[0], parent=self.__slidesDiv)
+ # HIDE_DONE notifications will trigger asynchronous pre-loading of the next image
+ self.__newSlide.subscribe(Slide.HIDE_DONE, self.__asyncPreload)
+ self.__oldSlide.subscribe(Slide.HIDE_DONE, self.__asyncPreload)
+ self.__currentIdx = 0
+ self.__changeSlide()
+ player.setInterval(CHANGE_INTERVAL, self.__changeSlide)
+
+ def __asyncPreload(self, slide):
+ self.__currentIdx = (self.__currentIdx + 1) % len(self.__imgFiles)
+ BitmapMgr.loadBitmap(self.__imgFiles[self.__currentIdx], slide.setBitmap)
+
+ def __changeSlide(self):
+ self.__oldSlide, self.__newSlide = self.__newSlide, self.__oldSlide
+ self.__slidesDiv.reorderChild(self.__newSlide, 1) # move to top
+ self.__newSlide.show()
+ self.__oldSlide.hide()
+
+
+if __name__ == '__main__':
+ app.App().run(Slideshow())
+
diff --git a/src/samples/subclass.py b/src/samples/subclass.py
new file mode 100755
index 0000000..b0b6380
--- /dev/null
+++ b/src/samples/subclass.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, gesture, app
+import libavg
+
+class TextRect(avg.DivNode):
+ def __init__(self, text, parent=None, **kwargs):
+ super(TextRect, self).__init__(**kwargs)
+ self.registerInstance(self, parent)
+ self.rect = avg.RectNode(size=self.size, fillopacity=1, fillcolor="000000",
+ color="FFFFFF", parent=self)
+ self.words = avg.WordsNode(color="FFFFFF", text=text, alignment="center",
+ parent=self)
+ self.words.pos = (self.size-(0,self.words.size.y)) / 2
+
+ def getSize(self):
+ return self.__divSize
+
+ def setSize(self, size):
+ self.rect.size = size
+ self.words.pos = (size-(0,self.words.size.y)) / 2
+ self.__divSize = size
+ __divSize = avg.DivNode.size
+ size = property(getSize, setSize)
+
+
+class SubclassDemo(app.MainDiv):
+
+ def onInit(self):
+ self.rect = TextRect(text="Hello World", pos=(20,20), size=(200,120),
+ parent=self)
+ self.__recognizer = gesture.TapRecognizer(node=self.rect,
+ detectedHandler=self.onTap)
+
+ def onTap(self):
+ self.rect.size = self.rect.size + (10,10)
+
+if __name__ == '__main__':
+ app.App().run(SubclassDemo(), app_resolution='800x600')
diff --git a/src/samples/timer.py b/src/samples/timer.py
new file mode 100755
index 0000000..9973d4e
--- /dev/null
+++ b/src/samples/timer.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+def moveText():
+ global node
+ node.x = 200
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+player.setTimeout(1000, moveText)
+
+player.play()
+
diff --git a/src/samples/timer2.py b/src/samples/timer2.py
new file mode 100755
index 0000000..006005d
--- /dev/null
+++ b/src/samples/timer2.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+def moveText():
+ global node
+ if node.x < 200:
+ node.x += 1
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+player.subscribe(player.ON_FRAME, moveText)
+
+player.play()
+
diff --git a/src/samples/timer3.py b/src/samples/timer3.py
new file mode 100755
index 0000000..492cdda
--- /dev/null
+++ b/src/samples/timer3.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+def moveText():
+ global node
+ if node.x < 200:
+ node.x += 20
+ else:
+ player.clearInterval(timer)
+
+canvas = player.createMainCanvas(size=(640,480))
+rootNode = canvas.getRootNode()
+node = avg.WordsNode(pos=(10,10), text="Hello World", parent=rootNode)
+timer = player.setInterval(200, moveText)
+
+player.play()
+
diff --git a/src/samples/twovideos.py b/src/samples/twovideos.py
new file mode 100755
index 0000000..1ad3fca
--- /dev/null
+++ b/src/samples/twovideos.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import libavg
+from libavg import avg, app, player
+
+
+class HDVideo(app.MainDiv):
+ def onArgvParserCreated(self, parser):
+ parser.set_usage('%prog <video1> <video2>')
+ parser.add_option('--duration', '-d', dest='duration',
+ default=2000, type='int', help='Crossfade duration')
+
+ def onArgvParsed(self, options, args, parser):
+ if len(args) != 2:
+ parser.print_help()
+ sys.exit(1)
+
+ self.__videos = args
+ self.__duration = options.duration
+
+ def onInit(self):
+ self.videoNodes = []
+ for fileName in (self.__videos[0], self.__videos[1]):
+ videoNode = avg.VideoNode(
+ size=(1680, 1050),
+ href=fileName,
+ opacity=0,
+ loop=True,
+ parent=self)
+ videoNode.play()
+ self.videoNodes.append(videoNode)
+
+ self.videoNodes[0].opacity = 1
+ self.runningVideo = 0
+ self.isFading = False
+
+ app.keyboardmanager.bindKeyDown('1', self.onButtonPressed,
+ 'Crossfade between videos')
+
+ def onButtonPressed(self):
+ if not(self.isFading):
+ if self.runningVideo == 0:
+ avg.fadeIn(self.videoNodes[1], self.__duration)
+ else:
+ avg.fadeOut(self.videoNodes[1], self.__duration)
+ player.setTimeout(self.__duration, self.fadeEnd)
+ self.runningVideo = (self.runningVideo+1)%2
+ self.isFading = True
+
+ def fadeEnd(self):
+ self.isFading = False
+
+app.App().run(HDVideo(), app_resolution='1680x1050', app_window_size='720x450')
diff --git a/src/samples/video.py b/src/samples/video.py
new file mode 100755
index 0000000..73d8c3e
--- /dev/null
+++ b/src/samples/video.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+videoNode = avg.VideoNode(href="mpeg1-48x48-sound.avi", pos=(10,10),
+ parent=rootNode)
+videoNode.play()
+player.play()
diff --git a/src/samples/videochooser.py b/src/samples/videochooser.py
new file mode 100755
index 0000000..c0f9fb4
--- /dev/null
+++ b/src/samples/videochooser.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os, sys
+from libavg import avg, app, player, Point2D
+
+
+class VideoChooser(app.MainDiv):
+ def onArgvParserCreated(self, parser):
+ parser.set_usage("%prog <folder>")
+ parser.add_option('--duration', '-d', dest='duration',
+ default=2000, type='int', help='Fade duration')
+ parser.add_option('--width', '-w', dest='thumbWidth',
+ default=320, type='int', help='Thumbnail width')
+
+ def onArgvParsed(self, options, args, parser):
+ if len(args) != 1:
+ parser.print_help()
+ sys.exit(1)
+
+ self.__folder = args[0]
+ self.__duration = options.duration
+ self.__thumbWidth = options.thumbWidth
+
+ def onInit(self):
+ player.showCursor(True)
+
+ self.videoListNode = avg.DivNode(parent=self)
+ self.videoNodes = []
+ fileNames = os.listdir(self.__folder)
+ i = 0
+ for fileName in fileNames:
+ try:
+ videoNode = avg.VideoNode(
+ pos=(i*(self.__thumbWidth+20), 0),
+ href=self.__folder+'/'+fileName,
+ loop=True,
+ mipmap=True,
+ enablesound=False,
+ parent = self.videoListNode)
+ videoNode.play()
+ self.videoNodes.append(videoNode)
+
+ size = videoNode.getMediaSize()
+ height = (self.__thumbWidth*size.y)/size.x
+ videoNode.size = (self.__thumbWidth, height)
+ videoNode.subscribe(videoNode.CURSOR_DOWN,
+ lambda event, videoNode=videoNode:
+ self.chooseVideo(event, videoNode))
+ i += 1
+ except RuntimeError:
+ pass
+
+ self.subscribe(self.CURSOR_MOTION, self.onMouseMove)
+ self.bigVideoNode = None
+
+ def onMouseMove(self, event):
+ windowWidth = player.getRootNode().width
+ ratio = event.x/float(windowWidth)
+ self.videoListNode.x = -(ratio*(self.getTotalWidth()-windowWidth))
+
+ def chooseVideo(self, event, videoNode):
+ if self.bigVideoNode:
+ self.removeBigVideo()
+ destSize = videoNode.size*2
+ destPos = Point2D(720, 550)-destSize/2
+ absPos = videoNode.getAbsPos(Point2D(0,0))
+ frame = videoNode.getCurFrame()
+ self.bigVideoNode = avg.VideoNode(href=videoNode.href, loop=True, sensitive=False,
+ parent=self)
+ self.bigVideoNode.play()
+ self.bigVideoNode.seekToFrame(frame)
+ avg.EaseInOutAnim(self.bigVideoNode, "pos", 1000, absPos, destPos, False,
+ 300, 300).start()
+ avg.EaseInOutAnim(self.bigVideoNode, "size", 1000, videoNode.size, destSize,
+ False, 300, 300).start()
+
+ def removeBigVideo(self):
+ oldVideoNode = self.bigVideoNode
+ avg.fadeOut(oldVideoNode, self.__duration, lambda: oldVideoNode.unlink(True))
+
+ def getTotalWidth(self):
+ return (self.__thumbWidth+20)*len(self.videoNodes)
+
+
+app.App().run(VideoChooser(), app_resolution='1440x900', app_window_size='720x450')
+
diff --git a/src/samples/widget.py b/src/samples/widget.py
new file mode 100755
index 0000000..0396299
--- /dev/null
+++ b/src/samples/widget.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, app, widget
+
+class SimpleUI(app.MainDiv):
+ def onInit(self):
+ avg.RectNode(size=(1024,768), fillopacity=1, fillcolor="FFFFFF",
+ parent=self)
+
+ hScrollBar = widget.ScrollBar(pos=(10,10), width=150, parent=self)
+ self.__addValueDisplay(hScrollBar, (175,12))
+
+ vScrollBar = widget.ScrollBar(pos=(15,60), height=150,
+ orientation=widget.Orientation.VERTICAL, parent=self)
+ vScrollBar.thumbExtent = 5
+ vScrollBar.range = (10,0)
+ self.__addValueDisplay(vScrollBar, (10,220))
+
+ hSlider = widget.Slider(pos=(10,35), width=150, parent=self)
+ self.__addValueDisplay(hSlider, (175,33))
+
+ vSlider = widget.Slider(pos=(60.5,60), height=150,
+ orientation=widget.Orientation.VERTICAL, parent=self)
+ vSlider.range = (1,0)
+ self.__addValueDisplay(vSlider, (55,220))
+ self.controls = [hScrollBar, vScrollBar, hSlider, vSlider]
+
+ self.createScrollArea(avg.Point2D(220,10))
+
+ checkBox = widget.CheckBox(pos=(10,270), text="Disable everything",
+ parent=self)
+ checkBox.subscribe(widget.CheckBox.TOGGLED, self.onCheck)
+
+ def setText(self, pos, node):
+ node.text = "%.2f"%pos
+
+ def setImageWidth(self, scrollArea, thumbPos):
+ scrollArea.contentsize = (thumbPos, scrollArea.contentsize.y)
+
+ def setImageHeight(self, scrollArea, thumbPos):
+ scrollArea.contentsize = (scrollArea.contentsize.x, thumbPos)
+
+ def createScrollArea(self, pos):
+ image = avg.ImageNode(href="rgb24-64x64.png", size=(1024, 1024))
+ scrollArea = widget.ScrollArea(contentNode=image, parent=self,
+ pos=pos, size=(220,220))
+
+ imageWidthSlider = widget.Slider(pos=pos+(0,230), width=220,
+ parent=self)
+ imageWidthSlider.range = (100,1024)
+ imageWidthSlider.thumbPos = 1024
+ imageWidthSlider.subscribe(widget.ScrollBar.THUMB_POS_CHANGED,
+ lambda thumbPos, scrollArea=scrollArea:
+ self.setImageWidth(scrollArea, thumbPos))
+
+ imageHeightSlider = widget.Slider(pos=pos+(230,0), height=220,
+ orientation=widget.Orientation.VERTICAL, parent=self)
+ imageHeightSlider.range = (100,1024)
+ imageHeightSlider.thumbPos = 1024
+ imageHeightSlider.subscribe(widget.ScrollBar.THUMB_POS_CHANGED,
+ lambda thumbPos, scrollArea=scrollArea:
+ self.setImageHeight(scrollArea, thumbPos))
+ self.controls.extend([scrollArea, imageWidthSlider, imageHeightSlider])
+
+ def onCheck(self, isChecked):
+ for node in self.controls:
+ node.enabled = not(isChecked)
+
+ def __addValueDisplay(self, scrollBar, pos):
+ textNode = avg.WordsNode(pos=pos, color="000000", parent=self)
+ scrollBar.subscribe(widget.ScrollBar.THUMB_POS_CHANGED,
+ lambda pos, node=textNode: self.setText(pos, node))
+ self.setText(scrollBar.thumbPos, textNode)
+
+
+app.App().run(SimpleUI(), app_resolution='1024x768')
diff --git a/src/samples/wordspos.py b/src/samples/wordspos.py
new file mode 100755
index 0000000..85a8ceb
--- /dev/null
+++ b/src/samples/wordspos.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libavg import avg, player
+
+canvas = player.createMainCanvas(size=(160,120))
+rootNode = canvas.getRootNode()
+avg.WordsNode(pos=(10,10), width=70, text="<i>Left-justified paragraph</i>",
+ parent=rootNode)
+avg.WordsNode(pos=(150,10), width=70, alignment="right", text="Right-justified paragraph",
+ parent=rootNode)
+avg.WordsNode(pos=(80,80), width=70, alignment="center", text="Centered paragraph",
+ parent=rootNode)
+player.play()
+