ahmedfgad / cointex Goto Github PK
View Code? Open in Web Editor NEWA cross-platform multi-level game created in Python using Kivy.
Home Page: https://play.google.com/store/apps/details?id=coin.tex.cointexreactfast
A cross-platform multi-level game created in Python using Kivy.
Home Page: https://play.google.com/store/apps/details?id=coin.tex.cointexreactfast
Seems to me from the code and the video demo that the agent exhibits two behaviours.
So if there is a monster at the midpoint of the player and the coin, but displaced from the coin by at least .3 in either direction, the agent will run directly into the monster because it only cares about danger at the destination but not the path. This seems to happen in the demo.
Some ideas are to (i) only consider solutions in the neighbourhood of the player (relative vector with bounds), or to (ii) change the fitness function to measure distance from the segment with endpoints at player and coin and (iii) consider the coin closest to the solution.
As it is the agent is exhibiting behaviour that could be easily found using simple path finding rather than GA.
I am not trying to be a jerk, just some pointers.
Here is the complete main.py file with my suggested code:
`import kivy.app
import kivy.uix.screenmanager
import kivy.uix.image
import random
import kivy.core.audio
import os
import functools
import kivy.uix.behaviors
import pickle
class TestApp(kivy.app.App):
# Class Property
music_dir = os.getcwd() + "/music/"
def __init__(self):
self.char_death_sound = kivy.core.audio.SoundLoader.load(self.music_dir + "char_death_flaute.wav")
self.level_completed_sound = kivy.core.audio.SoundLoader.load(self.music_dir + "level_completed_flaute.wav")
self.coin_sound = kivy.core.audio.SoundLoader.load(self.music_dir + "coin.wav")
self.bg_music = kivy.core.audio.SoundLoader.load(self.music_dir + "bg_music_piano.wav")
self.main_bg_music = kivy.core.audio.SoundLoader.load(self.music_dir + "bg_music_piano_flute.wav")
def on_start(self):
self.main_bg_music.loop = True
self.main_bg_music.play()
next_level_num, congrats_displayed_once = self.read_game_info()
self.activate_levels(next_level_num, congrats_displayed_once)
def read_game_info(self):
try:
game_info_file = open("game_info", 'rb')
game_info = pickle.load(game_info_file)
return game_info[0]['lastlvl'], game_info[0]['congrats_displayed_once']
game_info_file.close()
except:
print("CoinTex FileNotFoundError: Game info file is not found. Game starts from level 1.")
return 1, False
def activate_levels(self, next_level_num, congrats_displayed_once):
num_levels = len(self.root.screens[0].ids['lvls_imagebuttons'].children)
levels_imagebuttons = self.root.screens[0].ids['lvls_imagebuttons'].children
for i in range(num_levels - next_level_num, num_levels):
levels_imagebuttons[i].disabled = False
levels_imagebuttons[i].color = [1, 1, 1, 1]
for i in range(0, num_levels - next_level_num):
levels_imagebuttons[i].disabled = True
levels_imagebuttons[i].color = [1, 1, 1, 0.5]
if next_level_num == (num_levels + 1) and congrats_displayed_once == False:
self.root.current = "alllevelscompleted"
def screen_on_pre_leave(self, screen_num):
curr_screen = self.root.screens[screen_num]
for i in range(curr_screen.num_monsters): curr_screen.ids[
'monster' + str(i + 1) + '_image_lvl' + str(screen_num)].pos_hint = {'x': 0.8, 'y': 0.8}
curr_screen.ids['character_image_lvl' + str(screen_num)].pos_hint = {'x': 0.0, 'y': 0.0}
next_level_num, congrats_displayed_once = self.read_game_info()
self.activate_levels(next_level_num, congrats_displayed_once)
def screen_on_pre_enter(self, screen_num):
curr_screen = self.root.screens[screen_num]
curr_screen.character_killed = False
curr_screen.num_coins_collected = 0
curr_screen.ids['character_image_lvl' + str(screen_num)].im_num = curr_screen.ids[
'character_image_lvl' + str(screen_num)].start_im_num
for i in range(curr_screen.num_monsters): curr_screen.ids[
'monster' + str(i + 1) + '_image_lvl' + str(screen_num)].im_num = curr_screen.ids[
'monster' + str(i + 1) + '_image_lvl' + str(screen_num)].start_im_num
curr_screen.ids['num_coins_collected_lvl' + str(screen_num)].text = "Coins 0/" + str(curr_screen.num_coins)
curr_screen.ids['level_number_lvl' + str(screen_num)].text = "Level " + str(screen_num)
curr_screen.num_collisions_hit = 0
remaining_life_percent_lvl_widget = curr_screen.ids['remaining_life_percent_lvl' + str(screen_num)]
remaining_life_percent_lvl_widget.size_hint = (
remaining_life_percent_lvl_widget.remaining_life_size_hint_x, remaining_life_percent_lvl_widget.size_hint[1])
for i in range(curr_screen.num_fires): curr_screen.ids[
'fire' + str(i + 1) + '_lvl' + str(screen_num)].pos_hint = {'x': 1.1, 'y': 1.1}
for key, coin in curr_screen.coins_ids.items():
curr_screen.ids['layout_lvl' + str(screen_num)].remove_widget(coin)
curr_screen.coins_ids = {}
coin_width = 0.05
coin_height = 0.05
curr_screen = self.root.screens[screen_num]
section_width = 1.0 / curr_screen.num_coins
for k in range(curr_screen.num_coins):
x = random.uniform(section_width * k, section_width * (k + 1) - coin_width)
y = random.uniform(0, 1 - coin_height)
coin = kivy.uix.image.Image(source="coin.png", size_hint=(coin_width, coin_height),
pos_hint={'x': x, 'y': y}, allow_stretch=True)
curr_screen.ids['layout_lvl' + str(screen_num)].add_widget(coin, index=-1)
curr_screen.coins_ids['coin' + str(k)] = coin
def screen_on_enter(self, screen_num):
self.bg_music.loop = True
self.bg_music.play()
curr_screen = self.root.screens[screen_num]
for i in range(curr_screen.num_monsters):
monster_image = curr_screen.ids['monster' + str(i + 1) + '_image_lvl' + str(screen_num)]
new_pos = (random.uniform(0.0, 1 - monster_image.size_hint[0] / 4),
random.uniform(0.0, 1 - monster_image.size_hint[1] / 4))
self.start_monst_animation(monster_image=monster_image, new_pos=new_pos,
anim_duration=random.uniform(monster_image.monst_anim_duration_low,
monster_image.monst_anim_duration_high))
for i in range(curr_screen.num_fires):
fire_widget = curr_screen.ids['fire' + str(i + 1) + '_lvl' + str(screen_num)]
self.start_fire_animation(fire_widget=fire_widget, pos=(0.0, 0.5), anim_duration=5.0)
def start_monst_animation(self, monster_image, new_pos, anim_duration):
monst_anim = kivy.animation.Animation(pos_hint={'x': new_pos[0], 'y': new_pos[1]},
im_num=monster_image.end_im_num, duration=anim_duration)
monst_anim.bind(on_complete=self.monst_animation_completed)
monst_anim.start(monster_image)
def monst_animation_completed(self, *args):
monster_image = args[1]
monster_image.im_num = monster_image.start_im_num
new_pos = (random.uniform(0.0, 1 - monster_image.size_hint[0] / 4),
random.uniform(0.0, 1 - monster_image.size_hint[1] / 4))
self.start_monst_animation(monster_image=monster_image, new_pos=new_pos,
anim_duration=random.uniform(monster_image.monst_anim_duration_low,
monster_image.monst_anim_duration_high))
def monst_pos_hint(self, monster_image):
screen_num = int(monster_image.parent.parent.name[5:])
curr_screen = self.root.screens[screen_num]
character_image = curr_screen.ids['character_image_lvl' + str(screen_num)]
character_center = character_image.center
monster_center = monster_image.center
gab_x = character_image.width / 2
gab_y = character_image.height / 2
if character_image.collide_widget(monster_image) and abs(
character_center[0] - monster_center[0]) <= gab_x and abs(
character_center[1] - monster_center[1]) <= gab_y:
curr_screen.num_collisions_hit = curr_screen.num_collisions_hit + 1
life_percent = float(curr_screen.num_collisions_hit) / float(curr_screen.num_collisions_level)
# life_remaining_percent = 100-round(life_percent, 2)*100
# remaining_life_percent_lvl_widget.text = str(int(life_remaining_percent))+"%"
remaining_life_percent_lvl_widget = curr_screen.ids['remaining_life_percent_lvl' + str(screen_num)]
remaining_life_size_hint_x = remaining_life_percent_lvl_widget.remaining_life_size_hint_x
remaining_life_percent_lvl_widget.size_hint = (
remaining_life_size_hint_x - remaining_life_size_hint_x * life_percent,
remaining_life_percent_lvl_widget.size_hint[1])
if curr_screen.num_collisions_hit == curr_screen.num_collisions_level:
self.bg_music.stop()
self.char_death_sound.play()
curr_screen.character_killed = True
kivy.animation.Animation.cancel_all(character_image)
for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(
curr_screen.ids['monster' + str(i + 1) + '_image_lvl' + str(screen_num)])
for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(
curr_screen.ids['fire' + str(i + 1) + '_lvl' + str(screen_num)])
character_image.im_num = character_image.dead_start_im_num
char_anim = kivy.animation.Animation(im_num=character_image.dead_end_im_num, duration=1.0)
char_anim.start(character_image)
kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
def change_monst_im(self, monster_image):
monster_image.source = str(int(monster_image.im_num)) + ".png"
def touch_down_handler(self, screen_num, args):
curr_screen = self.root.screens[screen_num]
if curr_screen.character_killed == False:
self.start_char_animation(screen_num, args[1].spos)
def start_char_animation(self, screen_num, touch_pos):
curr_screen = self.root.screens[screen_num]
character_image = curr_screen.ids['character_image_lvl' + str(screen_num)]
character_image.im_num = character_image.start_im_num
char_anim = kivy.animation.Animation(pos_hint={'x': touch_pos[0] - character_image.size_hint[0] / 2,
'y': touch_pos[1] - character_image.size_hint[1] / 2},
im_num=character_image.end_im_num, duration=curr_screen.char_anim_duration)
char_anim.bind(on_complete=self.char_animation_completed)
char_anim.start(character_image)
def char_animation_completed(self, *args):
character_image = args[1]
character_image.im_num = character_image.start_im_num
def char_pos_hint(self, character_image):
screen_num = int(character_image.parent.parent.name[5:])
character_center = character_image.center
gab_x = character_image.width / 3
gab_y = character_image.height / 3
coins_to_delete = []
curr_screen = self.root.screens[screen_num]
for coin_key, curr_coin in curr_screen.coins_ids.items():
curr_coin_center = curr_coin.center
if character_image.collide_widget(curr_coin) and abs(
character_center[0] - curr_coin_center[0]) <= gab_x and abs(
character_center[1] - curr_coin_center[1]) <= gab_y:
self.coin_sound.play()
coins_to_delete.append(coin_key)
curr_screen.ids['layout_lvl' + str(screen_num)].remove_widget(curr_coin)
curr_screen.num_coins_collected = curr_screen.num_coins_collected + 1
curr_screen.ids['num_coins_collected_lvl' + str(screen_num)].text = "Coins " + str(
curr_screen.num_coins_collected) + "/" + str(curr_screen.num_coins)
if curr_screen.num_coins_collected == curr_screen.num_coins:
self.bg_music.stop()
self.level_completed_sound.play()
kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(
curr_screen.ids['monster' + str(i + 1) + '_image_lvl' + str(screen_num)])
for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(
curr_screen.ids['fire' + str(i + 1) + '_lvl' + str(screen_num)])
next_level_num, congrats_displayed_once = self.read_game_info()
if (screen_num + 1) > next_level_num:
game_info_file = open("game_info", 'wb')
pickle.dump([{'lastlvl': screen_num + 1, "congrats_displayed_once": False}], game_info_file)
game_info_file.close()
else:
game_info_file = open("game_info", 'wb')
pickle.dump([{'lastlvl': next_level_num, "congrats_displayed_once": True}], game_info_file)
game_info_file.close()
if len(coins_to_delete) > 0:
for coin_key in coins_to_delete:
del curr_screen.coins_ids[coin_key]
def change_char_im(self, character_image):
character_image.source = str(int(character_image.im_num)) + ".png"
def start_fire_animation(self, fire_widget, pos, anim_duration):
fire_anim = kivy.animation.Animation(pos_hint=fire_widget.fire_start_pos_hint,
duration=fire_widget.fire_anim_duration) + kivy.animation.Animation(
pos_hint=fire_widget.fire_end_pos_hint, duration=fire_widget.fire_anim_duration)
fire_anim.repeat = True
fire_anim.start(fire_widget)
def fire_pos_hint(self, fire_widget):
screen_num = int(fire_widget.parent.parent.name[5:])
curr_screen = self.root.screens[screen_num]
character_image = curr_screen.ids['character_image_lvl' + str(screen_num)]
character_center = character_image.center
fire_center = fire_widget.center
gab_x = character_image.width / 3
gab_y = character_image.height / 3
if character_image.collide_widget(fire_widget) and abs(character_center[0] - fire_center[0]) <= gab_x and abs(
character_center[1] - fire_center[1]) <= gab_y:
curr_screen.num_collisions_hit = curr_screen.num_collisions_hit + 1
life_percent = float(curr_screen.num_collisions_hit) / float(curr_screen.num_collisions_level)
remaining_life_percent_lvl_widget = curr_screen.ids['remaining_life_percent_lvl' + str(screen_num)]
# life_remaining_percent = 100-round(life_percent, 2)*100
# remaining_life_percent_lvl_widget.text = str(int(life_remaining_percent))+"%"
remaining_life_size_hint_x = remaining_life_percent_lvl_widget.remaining_life_size_hint_x
remaining_life_percent_lvl_widget.size_hint = (
remaining_life_size_hint_x - remaining_life_size_hint_x * life_percent,
remaining_life_percent_lvl_widget.size_hint[1])
if curr_screen.num_collisions_hit == curr_screen.num_collisions_level:
self.bg_music.stop()
self.char_death_sound.play()
curr_screen.character_killed = True
kivy.animation.Animation.cancel_all(character_image)
for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(
curr_screen.ids['monster' + str(i + 1) + '_image_lvl' + str(screen_num)])
for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(
curr_screen.ids['fire' + str(i + 1) + '_lvl' + str(screen_num)])
character_image.im_num = character_image.dead_start_im_num
char_anim = kivy.animation.Animation(im_num=character_image.dead_end_im_num, duration=1.0)
char_anim.start(character_image)
kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
def back_to_main_screen(self, screenManager, *args):
screenManager.current = "main"
def main_screen_on_enter(self):
self.main_bg_music.play()
def main_screen_on_leave(self):
self.main_bg_music.stop()
class ImageButton(kivy.uix.behaviors.ButtonBehavior, kivy.uix.image.Image):
pass
class MainScreen(kivy.uix.screenmanager.Screen):
pass
class AboutUs(kivy.uix.screenmanager.Screen):
pass
class AllLevelsCompleted(kivy.uix.screenmanager.Screen):
pass
class Level1(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 5
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.0
num_monsters = 1
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 20
class Level2(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 8
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.1
num_monsters = 1
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 30
class Level3(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 12
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.2
num_monsters = 1
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 30
class Level4(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 10
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.2
num_monsters = 1
num_fires = 1
num_collisions_hit = 0
num_collisions_level = 20
class Level5(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.3
num_monsters = 1
num_fires = 2
num_collisions_hit = 0
num_collisions_level = 20
class Level6(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 12
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.3
num_monsters = 1
num_fires = 3
num_collisions_hit = 0
num_collisions_level = 20
class Level7(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 10
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.4
num_monsters = 3
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 25
class Level8(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.4
num_monsters = 2
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 25
class Level9(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 12
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.5
num_monsters = 2
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 25
class Level10(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 14
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.5
num_monsters = 3
num_fires = 0
num_collisions_hit = 0
num_collisions_level = 30
class Level11(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.6
num_monsters = 2
num_fires = 1
num_collisions_hit = 0
num_collisions_level = 30
class Level12(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 12
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.6
num_monsters = 2
num_fires = 1
num_collisions_hit = 0
num_collisions_level = 30
class Level13(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 10
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.7
num_monsters = 2
num_fires = 2
num_collisions_hit = 0
num_collisions_level = 20
class Level14(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.7
num_monsters = 0
num_fires = 6
num_collisions_hit = 0
num_collisions_level = 30
class Level15(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 16
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.8
num_monsters = 2
num_fires = 3
num_collisions_hit = 0
num_collisions_level = 30
class Level16(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.8
num_monsters = 3
num_fires = 2
num_collisions_hit = 0
num_collisions_level = 35
class Level17(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 10
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.3
num_monsters = 0
num_fires = 4
num_collisions_hit = 0
num_collisions_level = 30
class Level18(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.5
num_monsters = 3
num_fires = 4
num_collisions_hit = 0
num_collisions_level = 30
class Level19(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 12
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.2
num_monsters = 0
num_fires = 6
num_collisions_hit = 0
num_collisions_level = 30
class Level20(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 15
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.1
num_monsters = 0
num_fires = 8
num_collisions_hit = 0
num_collisions_level = 30
class Level20(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 20
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.1
num_monsters = 2
num_fires = 4
num_collisions_hit = 0
num_collisions_level = 30
class Level21(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 18
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.3
num_monsters = 2
num_fires = 4
num_collisions_hit = 0
num_collisions_level = 30
class Level22(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 20
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.3
num_monsters = 2
num_fires = 4
num_collisions_hit = 0
num_collisions_level = 30
class Level23(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 25
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.1
num_monsters = 2
num_fires = 2
num_collisions_hit = 0
num_collisions_level = 30
class Level24(kivy.uix.screenmanager.Screen):
character_killed = False
num_coins = 20
num_coins_collected = 0
coins_ids = {}
char_anim_duration = 1.1
num_monsters = 3
num_fires = 2
num_collisions_hit = 0
num_collisions_level = 30
app = TestApp(title="CoinTex")
app.run()
`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.