Coder Social home page Coder Social logo

ahmedfgad / cointex Goto Github PK

View Code? Open in Web Editor NEW
74.0 8.0 26.0 15.9 MB

A cross-platform multi-level game created in Python using Kivy.

Home Page: https://play.google.com/store/apps/details?id=coin.tex.cointexreactfast

Python 38.80% kvlang 61.20%
kivy python android linux cross-platform game kv-lang kivy-framework multi-level python3

cointex's People

Contributors

ahmedfgad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cointex's Issues

Agent ignores its own position, and hazards in its path

Seems to me from the code and the video demo that the agent exhibits two behaviours.

  • Find position closest to the first coin in dictionary
  • Subject to constraint that it is not contained in a .3x.3 bounding box of any hazards

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.

Main.py Suggestions

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()
`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.