From 1bbbcb69db0538659a7a3146060c09d45ed780ef Mon Sep 17 00:00:00 2001 From: Thadeus Burgess Date: Sat, 21 Jan 2012 23:42:46 -0600 Subject: [PATCH] Simple ellipse collision code from Phyces pygame tutorial ported to kivy --- kworld/create_apk.sh | 10 +++ kworld/main.py | 146 ++++++++++++++++++++++++++++++++++ kworld/main_big_byte.py | 172 ++++++++++++++++++++++++++++++++++++++++ notes.txt | 10 +++ painter/main.py | 19 ++++- 5 files changed, 355 insertions(+), 2 deletions(-) create mode 100755 kworld/create_apk.sh create mode 100644 kworld/main.py create mode 100644 kworld/main_big_byte.py create mode 100644 notes.txt diff --git a/kworld/create_apk.sh b/kworld/create_apk.sh new file mode 100755 index 0000000..0640989 --- /dev/null +++ b/kworld/create_apk.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export PATH=$PATH:/home/thadeusb/Workspace/Android/android-sdk-linux/tools/:/home/thadeusb/Workspace/Android/android-sdk-linux/platform-tools +cd /home/thadeusb/Workspace/Android/Kivy-1.0.9-android/ +rm -rf bin +rm -rf ~/.android/debug.keystore +adb uninstall org.thadeusb.kworld +python build.py --dir /home/thadeusb/Workspace/KivyPlayground/kworld --package org.thadeusb.kworld --name "Kaboodle World" --version 1.0.0 debug installd +# adb -d install -r /home/thadeusb/Workspace/Android/Kivy-1.0.9-android/bin/KaboodleWorld-1.0.0-debug.apk +cd /home/thadeusb/Workspace/KivyPlayground/kworld diff --git a/kworld/main.py b/kworld/main.py new file mode 100644 index 0000000..4841c4e --- /dev/null +++ b/kworld/main.py @@ -0,0 +1,146 @@ +import kivy + +kivy.require('1.0.9') + +import random + +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.uix.image import Image +from kivy.vector import Vector +from kivy.clock import Clock +from kivy.graphics import Color, Ellipse, Line, Rectangle +from kivy.properties import NumericProperty, ReferenceListProperty +from kivy.vector import Vector + +FPS = 1.0/60.0 + +class Agent(): + def __init__(self): + self.pos = Vector(0,0) + self.target = Vector(0,0) + +class KaboodleGame(Widget): + def __init__(self, *args, **kwargs): + super(KaboodleGame, self).__init__(*args, **kwargs) + + self.initialized = False + + Clock.schedule_once(self.initialize) + + def initialize(self, dt): + self.initialized = True + + try: + self.window_width + self.window_height + except AttributeError: + win = self.get_parent_window() + + self.window_width = win.width + self.window_height = win.height + + self.agents = [] + + for i in range(30): + a = Agent() + a.pos = Vector(random.uniform(0, self.window_width), + random.uniform(0, self.window_height)) + a.target = Vector(random.uniform(0, self.window_width), + random.uniform(0, self.window_height)) + + self.agents.append(a) + + self.selected = self.agents[random.randrange(0, len(self.agents))] + + Clock.schedule_interval(self.update, FPS) + Clock.schedule_interval(self.alter_targets, 5) + + def alter_targets(self, dt): + for a in self.agents: + if a == self.selected: + continue + + a.target = Vector(random.uniform(0, self.window_width), + random.uniform(0, self.window_height)) + + def on_touch_down(self, touch): + for a in self.agents: + if a.pos.distance(Vector(touch.x, touch.y)) < 20: + self.selected = a + + def on_touch_up(self, touch): + self.selected.target = Vector(touch.x, touch.y) + + def update(self, dt): + for agent in self.agents: + dir = agent.target - agent.pos + + if dir.length() > 8: + agent.pos += dir.normalize() * 7 + + for a in self.agents: + for a2 in self.agents: + if a2 == a: + continue + + d = a.pos.distance(a2.pos) + + if 2 < d < 44: + # resolve collision + overlap = 44 - d + + if self.selected in (a, a2): + if a2 == self.selected: + other = a + else: + other = a2 + + direction = other.pos - self.selected.pos + direction = direction.normalize() * overlap / 2 + + other.pos += direction + else: + direction = a2.pos - a.pos + direction = direction.normalize() * overlap / 2 + + a2.pos += direction + a.pos -= direction + + self.draw() + + def draw(self): + self.canvas.clear() + + with self.canvas: + Color(1,1,1) + Rectangle(pos=(0,0), size=self.size) + + for agent in self.agents: + Color(1,0,0) + Ellipse(pos=(agent.target[0]-15, + agent.target[1]-15), size=(30*2, 30*2)) + Color(1,1,1) + Ellipse(pos=(agent.target[0]-15+1, + agent.target[1]-15+1), size=(29*2, 29*2)) + + for agent in self.agents: + Color(0,0,0) + Ellipse(pos=(agent.pos[0]-10-1, + agent.pos[1]-10-1), size=(21*2,21*2)) + + if agent == self.selected: + Color(200/255.0,250/255.0,1) + else: + Color(200/255.0,200/255.0,1) + + Ellipse(pos=(agent.pos[0]-10, + agent.pos[1]-10), size=(20*2, 20*2)) + +class KaboodleWorldApp(App): + def build(self): + game = KaboodleGame() + return game + +if __name__ in ('__android__', '__main__'): + KaboodleWorldApp().run() diff --git a/kworld/main_big_byte.py b/kworld/main_big_byte.py new file mode 100644 index 0000000..2b0d417 --- /dev/null +++ b/kworld/main_big_byte.py @@ -0,0 +1,172 @@ +import kivy + +kivy.require('1.0.9') + +import random + +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.vector import Vector +from kivy.clock import Clock +from kivy.graphics import Color, Ellipse, Line, Rectangle +from kivy.properties import NumericProperty, ReferenceListProperty +from kivy.vector import Vector + +FPS = 1.0/60.0 + +class Noodle(Widget): + SPEED = 4 + ENERGY_CONSUMPTION = .1 + + size = (5,5) + + velocity_x = NumericProperty(0) + velocity_y = NumericProperty(0) + + velocity = ReferenceListProperty(velocity_x, velocity_y) + + def __init__(self, velocity=(0,0), **kwargs): + super(Noodle, self).__init__(**kwargs) + + self.velocity = velocity + self.speed = Noodle.SPEED + + self.hunger = 100 + + self.color = (1, random.random(), random.random()) + + self.velocity_x += random.random() - random.random() + self.velocity_y += random.random() - random.random() + + def update(self, *args): + self.move() + + food = self.parent.i_collide_food(self) + + if food: + self.eat(food) + + self.render() + + def move(self): + self.pos = Vector(*self.velocity) + self.pos + + if (self.x < 0) or (self.right > self.parent.window_width): + self.velocity_x *= -1 + if (self.y < 0) or (self.top > self.parent.window_height): + self.velocity_y *= -1 + + self.hunger -= Noodle.ENERGY_CONSUMPTION + + if self.hunger <= 0: + self.die() + + def render(self): + self.canvas.clear() + with self.canvas: + Color(*self.color) + Rectangle(pos=self.pos, size=self.size) + + def die(self): + Clock.unschedule(self.update) + + if not self.parent: + return + + def end(dt): + if self.parent: + self.parent.remove_widget(self) + + Clock.schedule_once(end, 0.25) + + def eat(self, food): + self.hunger += food.energy_potential + + self.parent.remove_widget(food) + self.parent.food.remove(food) + +class Food(Widget): + ENERGY_POTENTIAL = 15 + + size = (5,5) + + def __init__(self, energy_potential=ENERGY_POTENTIAL, **kwargs): + super(Food, self).__init__(**kwargs) + + self.energy_potential = energy_potential + + def update(self, *args): + self.canvas.clear() + with self.canvas: + Color(0, 0, 0) + Ellipse(pos=self.pos, size=self.size) + +class KaboodleGame(Widget): + + def __init__(self, *args, **kwargs): + super(KaboodleGame, self).__init__(*args, **kwargs) + + self.initialized = False + self.food = [] + self.noodles = [] + + Clock.schedule_once(self.initialize) + Clock.schedule_interval(self.update, FPS) + Clock.schedule_interval(self.spawn_food, 5) + + def initialize(self, dt): + self.initialized = True + + try: + self.window_width + self.window_height + except AttributeError: + win = self.get_parent_window() + + self.window_width = win.width + self.window_height = win.height + + self.add_noodles() + self.spawn_food() + + def add_noodles(self): + for i in range(50): + person = Noodle(pos=(random.randrange(self.window_width), + random.randrange(self.window_height))) + self.noodles.append(person) + self.add_widget(person) + + def spawn_food(self, dt=0.0): + + for i in range(5): + x_center = random.randrange(self.window_width) + y_center = random.randrange(self.window_height) + + for i in range(15): + x = random.randrange(x_center-15, x_center+15) + y = random.randrange(y_center-15, y_center+15) + + if 0 < x < self.window_width \ + and 0 < y < self.window_height: + food = Food(pos=(x, y)) + self.food.append(food) + self.add_widget(food) + + + + def update(self, *args): + self.canvas.before.clear() + with self.canvas.before: + Color(.2, .5, .2) + Rectangle(pos=(0,0), size=self.size) + + for noodle in self.noodles: + noodle.update() + +class KaboodleWorldApp(App): + def build(self): + game = KaboodleGame() + return game + +if __name__ in ('__android__', '__main__'): + KaboodleWorldApp().run() diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..d794f1e --- /dev/null +++ b/notes.txt @@ -0,0 +1,10 @@ +PATH=$PATH:/home/thadeusb/Workspace/Android/android-sdk-linux/tools/:/home/thadeusb/Workspace/Android/android-sdk-linux/platform-tools + +./adb install -r ../../Kivy-1.0.9-android/bin/PongGame-1.0.6-debug.apk + +python build.py --dir ~/Workspace/KivyPlayground/pong + --package org.demo.pong + --name "Pong Game" + --version 1.0.6 debug + + install diff --git a/painter/main.py b/painter/main.py index 1f89991..29e0b1b 100644 --- a/painter/main.py +++ b/painter/main.py @@ -4,12 +4,25 @@ from kivy.uix.widget import Widget from kivy.uix.button import Button from kivy.graphics import Color, Ellipse, Line +from kivy.core.window import Window +from kivy.logger import Logger CircleSize = 30.0 class MyPaintWidget(Widget): + + def on_motion(self, etype, motionevent, *args): + Logger.info(str(self)) + Logger.info(str(etype)) + Logger.info(str(motionevent)) + Logger.info(str(args)) + def on_touch_down(self, touch): + + Window.bind(on_motion=self.on_motion) + + touch.ud['color'] = (random.random(), 1, 1) with self.canvas: Color(*touch.ud['color'], mode='hsv') @@ -19,9 +32,11 @@ def on_touch_down(self, touch): touch.ud['line'] = Line(points=(touch.x, touch.y)) def on_touch_move(self, touch): - touch.ud['line'].points += [touch.x, touch.y] + touch.ud['line'].points += [touch.x, touch.y] + class MyPaintApp(App): + def build(self): parent = Widget() painter = MyPaintWidget() @@ -34,7 +49,7 @@ def clear_canvas(obj): painter.canvas.clear() clearbtn.bind(on_release=clear_canvas) - + return parent if __name__ in ('__android__', '__main__'):