Skip to content

Commit

Permalink
Improved particle engine, moved away from using fbo because it is slo…
Browse files Browse the repository at this point in the history
…wer than canvas directly
  • Loading branch information
Kovak committed Aug 21, 2013
1 parent 427c220 commit fc79d3d
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 50 deletions.
1 change: 0 additions & 1 deletion kivent_cython/kivent_cython/gamesystems.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class GameSystem(Widget):
self.entity_ids.append(entity_id)

def generate_entity_component_dict(self, int entity_id):
#This is the save function
cdef dict entity = self.gameworld.entities[entity_id]
return entity[self.system_id]

Expand Down
6 changes: 3 additions & 3 deletions kivent_cython/kivent_cython/particleemitter.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class ParticleEmitter(Widget):
group_id = str(entity['id'])
current_scroll = self.current_scroll
color = particle.color[:]
#with self.particle_manager.canvas:
with self.fbo:
with self.particle_manager.canvas:
#with self.fbo:
PushMatrix(group=group_id)
particle_manager['color'] = Color(color[0], color[1],
color[2], color[3], group=group_id)
Expand Down Expand Up @@ -134,7 +134,7 @@ class ParticleEmitter(Widget):

def free_particle(self, entity_id):
particles = self.particles
self.fbo.remove_group(str(entity_id))
self.particle_manager.canvas.remove_group(str(entity_id))
self.particle_manager.free_particle(particles.pop(particles.index(entity_id)))

def on_life_span(self,instance,value):
Expand Down
50 changes: 19 additions & 31 deletions kivent_cython/kivent_cython/particlemanager.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from kivy.graphics import Fbo, Rectangle, Color
from kivy.graphics.opengl import (glBlendFunc, GL_SRC_ALPHA, GL_ONE,
GL_ZERO, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA,
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR)
from libc.math cimport trunc


BLEND_FUNC = {
Expand Down Expand Up @@ -39,9 +40,9 @@ class ParticleManager(GameSystem):
super(ParticleManager, self).__init__(**kwargs)


with self.canvas:
self.fbo = Fbo(size=self.size, clear_color=(0., 0., 0., 1.))
self.fbo_rectangle = Rectangle(size=self.size, texture=self.fbo.texture)
#with self.canvas:
# self.fbo = Fbo(size=self.size, clear_color=(0., 0., 0., 1.))
# self.fbo_rectangle = Rectangle(size=self.size, texture=self.fbo.texture)
with self.canvas.before:
Callback(self._set_blend_func)
with self.canvas.after:
Expand All @@ -51,13 +52,13 @@ class ParticleManager(GameSystem):
self.particles = []
Clock.schedule_once(self.init_particles)

def update_fbo_texture(self):
self.fbo_rectangle.texture = self.fbo.texture
# def update_fbo_texture(self):
# self.fbo_rectangle.texture = self.fbo.texture

def on_size(self, instance, value):
self.fbo.size = value
self.fbo_rectangle.size = value
self.update_fbo_texture()
# def on_size(self, instance, value):
# self.fbo.size = value
# self.fbo_rectangle.size = value
# self.update_fbo_texture()

def _set_blend_func(self, instruction):
glBlendFunc(self.blend_factor_source, self.blend_factor_dest)
Expand All @@ -69,7 +70,6 @@ class ParticleManager(GameSystem):
def init_particles(self, dt):
particles = self.particles
entities = self.gameworld.entities
print self.max_number_particles, 'max number particles'
for x in xrange(self.max_number_particles):
entity_id = self.gameworld.init_entity({}, [])
entities[entity_id]['particle_manager'] = {'particle': Particle()}
Expand All @@ -82,8 +82,7 @@ class ParticleManager(GameSystem):
pass

def on_current_number_of_particles(self, instance, value):
if value > self.max_number_particles:
print 'recalculating particle limits'
pass


def load_particle_config(self, config):
Expand Down Expand Up @@ -260,19 +259,6 @@ class ParticleManager(GameSystem):
del particle_system
super(ParticleManager, self).remove_entity(entity_id)

def on_paused(self, instance, value):
cdef list entities = self.gameworld.entities
cdef str system_data_from = self.system_id
cdef dict entity
cdef dict particle_systems
cdef object particle_system
if value == True:
for entity_id in self.entity_ids:
entity = entities[entity_id]
particle_systems = entity[system_data_from]
for particle_effect in particle_systems:
particle_system = particle_systems[particle_effect]['particle_system']
particle_system.pause(with_clear = True)

def update(self, dt):
cdef dict systems = self.gameworld.systems
Expand All @@ -284,27 +270,29 @@ class ParticleManager(GameSystem):
cdef dict entity
cdef dict particle_systems
cdef object particle_system
self.fbo.bind()
self.fbo.clear_buffer()
self.fbo.release()
# self.fbo.bind()
# self.fbo.clear_buffer()
# self.fbo.release()
for entity_id in self.entity_ids:
entity = entities[entity_id]
particle_systems = entity[system_data_from]
for particle_effect in particle_systems:
particle_system = particle_systems[particle_effect]['particle_system']
if entity[render_information_from]['on_screen']:
if particle_systems[particle_effect]['particle_system_on']:
particle_system.current_scroll = camera_pos
if 'ignore_camera' not in particle_systems[particle_effect]:
particle_system.current_scroll = camera_pos
particle_system.pos = self.calculate_particle_offset(entity_id, particle_effect)
particle_system.emit_angle = radians(entity[position_data_from]['angle']+270)
time_between_particles = 1.0 / particle_system.emission_rate
particle_system.frame_time += dt
particle_system.update(dt)
while particle_system.frame_time > 0:
number_of_updates = trunc(particle_system.frame_time / time_between_particles)
particle_system.frame_time -= time_between_particles * number_of_updates
for x in xrange(int(number_of_updates)):
if self.particles != []:
particle = self.particles.pop()
particle_system.receive_particle(particle)
particle_system.frame_time -= time_between_particles
else:
if particle_system.particles != []:
particle_system.free_all_particles()
Expand Down
44 changes: 29 additions & 15 deletions yacs_ui_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivent_cython import (GameScreenManager, GameScreen)
from particlesystem import ParticleSystem
from kivy.clock import Clock

class YACSLabel(Label):
Expand All @@ -33,22 +32,39 @@ class CharacterInputPanel(Widget):
particle_system = ObjectProperty(None)
def __init__(self, **kwargs):
super(CharacterInputPanel, self).__init__(**kwargs)
self.create_touch_event_effect()
Clock.schedule_once(self.create_touch_event_effect)

def create_touch_event_effect(self):
self.particle_system = ParticleSystem(self.touch_effect)
def create_touch_event_effect(self, dt):
if self.gameworld.systems == {}:
Clock.schedule_once(self.create_touch_event_effect)
else:
particle_system = {'particle_file': self.touch_effect, 'offset': 0, 'ignore_camera': True}
particle_systems = {'effect1': particle_system}
create_dict = {'particle_manager': particle_systems}
component_order = ['particle_manager']
entity_id = self.gameworld.init_entity(create_dict, component_order)
self.particle_system = entity_id
self.gameworld.entities[entity_id]['cymunk-physics'] = {
'position': (self.size[0]/2. - 100, self.size[1]/2.),
'angle': 0.}
self.gameworld.entities[entity_id]['physics_renderer'] = {'on_screen': True}



def determine_touch_values(self, touch_x, touch_y):
x_value = (touch_x - self.pos[0])/self.size[0]
y_value = (touch_y - self.pos[1])/self.size[1]
return (x_value, y_value)

def on_current_touch(self, instance, value):
player_character = self.gameworld.systems['player_character']
gameworld = self.gameworld
player_character = gameworld.systems['player_character']
if not value == []:
touch_values = self.determine_touch_values(value[0], value[1])
particle_system = self.particle_system
particle_system.pos = value
particle_system_id = self.particle_system
particle_system_entity = gameworld.entities[particle_system_id]
particle_system = particle_system_entity['particle_manager']['effect1']['particle_system']
particle_system_entity['cymunk-physics']['position'] = value
particle_system.start_color = [touch_values[1], .3, .0, 1.]
particle_system.end_color = [touch_values[1], .0, .5, 1.]
player_character.touch_values = touch_values
Expand All @@ -59,10 +75,9 @@ def on_current_touch(self, instance, value):
def on_touch_down(self, touch):
if self.collide_point(touch.x, touch.y):
self.current_touch = (touch.x, touch.y)
particle_system = self.particle_system
particle_system.start()
if particle_system not in self.children:
self.add_widget(particle_system)
particle_system_id = self.particle_system
particle_system_entity = self.gameworld.entities[particle_system_id]
particle_system_entity['particle_manager']['effect1']['particle_system_on'] = True

def on_touch_move(self, touch):
if self.collide_point(touch.x, touch.y):
Expand All @@ -72,10 +87,9 @@ def on_touch_move(self, touch):
def on_touch_up(self, touch):
if self.collide_point(touch.x, touch.y):
self.current_touch = []
particle_system = self.particle_system
particle_system.stop()
if particle_system in self.children:
self.remove_widget(particle_system)
particle_system_id = self.particle_system
particle_system_entity = self.gameworld.entities[particle_system_id]
particle_system_entity['particle_manager']['effect1']['particle_system_on'] = False


class DebugPanel(Widget):
Expand Down

0 comments on commit fc79d3d

Please sign in to comment.