Giter Site home page Giter Site logo

gamezero.jl's People

Contributors

albinahlback avatar aviks avatar danilo-bc avatar dustyirwin avatar ginkulv avatar giordano avatar github-actions[bot] avatar kerkmann avatar rick2047 avatar scottbigbrain avatar squidsinker avatar testercwt 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  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

gamezero.jl's Issues

Attempting to load resource files crashes

I am attempting to make a game in Julia 1.10.0, and whenever I try to create an Actor or TextActor, the error below appears.
image

Does anyone know what's going on? The same error appears regardless of the assets being present or not.

GameZero opens a window four times bigger than defined

Hi, following up the discussion on JuliaCon discord, here is the report of the bug I found on my system. The game only uses a quarter of the window. I think it actually displays a window which is twice wide and twice taller than defined.

I attach screenshots of two of the games form SquidSinker/GZExamples. They define HEIGHT = 600 and WIDTH = 600, but the windows have twice the height and twice the width, as seen from the pixel count on the screenshots.

Here is the info of my set up:

(gamezero) pkg> st
      Status `~/Documents/git_repositories/julia/julia_random_stuff/gamezero/Project.toml`
  [5ae59095] Colors v0.12.8
  [9da27670] GameZero v0.2.1

julia> versioninfo()
Julia Version 1.6.2
Commit 1b93d53fc4 (2021-07-14 15:36 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin18.7.0)
  CPU: Intel(R) Core(TM) m5-6Y54 CPU @ 1.10GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 2

Screen Shot 2021-08-02 at 13 08 47

Screen Shot 2021-08-02 at 13 07 01

P.S.: The sound issue that I also mentioned didn't happen again. Sound is coming out fine. I might have done something wrong. Great, one less problem!

Stylistic convention

In order to have the same style as Julia, methods like getPos should be changed (if needed) to something like getpos.

UndefVarError: libsdl2_{ttf,image} not defined (Apple Silicon / M1 Mac)

I tried to run the file in the example directory and got an error. I see the same error when I tried GZExamples. Any idea? I installed master of SimpleMediaLayer and GameZero. I'm on M1 Mac and sdl2 libraries are installed by homebrew.

julia> using GameZero
julia> rungame("~/.julia/packages/GameZero/e03cc/example/BasicGame/basic.jl")
ERROR: UndefVarError: libsdl2_ttf not defined
Stacktrace:
 [1] TTF_Init
   @ ~/.julia/packages/SimpleDirectMediaLayer/gJANO/src/LibSDL2.jl:5233 [inlined]
 [2] initSDL()
   @ GameZero ~/.julia/packages/GameZero/17XG0/src/GameZero.jl:284
 [3] initgame(jlf::String, external::Bool)
   @ GameZero ~/.julia/packages/GameZero/17XG0/src/GameZero.jl:208
 [4] rungame(jlf::String, external::Bool)
   @ GameZero ~/.julia/packages/GameZero/17XG0/src/GameZero.jl:186
 [5] rungame(jlf::String)
   @ GameZero ~/.julia/packages/GameZero/17XG0/src/GameZero.jl:185
 [6] top-level scope
   @ REPL[5]:1
julia> versioninfo()
Julia Version 1.7.2
Commit bf53498635 (2022-02-06 15:21 UTC)
Platform Info:
  OS: macOS (arm64-apple-darwin21.2.0)
  CPU: Apple M1 Max
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, cyclone)
Environment:
  JULIA_GR_PROVIDER = GR
(@v1.7) pkg> st GameZero SimpleDirectMediaLayer
      Status `~/.julia/environments/v1.7/Project.toml`
  [9da27670] GameZero v0.3.0 `https://github.com/aviks/GameZero.jl.git#master`
  [98e33af6] SimpleDirectMediaLayer v0.3.0 `https://github.com/JuliaMultimedia/SimpleDirectMediaLayer.jl.git#master`
$ brew list|grep sdl2
sdl2
sdl2_gfx
sdl2_image
sdl2_mixer
sdl2_net
sdl2_ttf

Actors vanish after some time...

I'm having some problems with the actors that I load into a game.

After some time (I haven't yet been able to determine a rhyme or reason yet, but usually after there are a few sprites in play or after 10~15 seconds) the actors all disappear and I'm left with an empty screen. I can still hear music and sounds being activated, just no visuals. Closing the game and reloading usually works (sometime it just hangs, forcing a Julia reboot) and it will draw the actors again until they disappear again.

Has anyone else had a similar issue?

Draw basic forms (Rect, Triangle) with angle

I would like to draw some basic forms with soma angle.
I looked aroud the code and didn't find anything to do that.
Is there some native way of doing it?
If there is not, I could implement my own simple Rect object made with four Lines, but I dont know how to fill this 4 lines in the Draw function

Text

Implement a way to print text in the game screen.

`Circle` does not have same properties as `Actor` e.g. actor.pos, actor.position

Based on the docs, I got the impression that Circle should have the same properties as Actor. So I ran into an problem where my code runs on actors using a.pos, but then it didn't work with Circles e.g. c.pos was "nothing".

Circle has the same API/properties as Actor.
Game objects on-screen are represented as Actors which have several associated attributes. Using Actors, you can change position, change the image and check for collisions. However, not all moving parts need to be Actors as those without a specific image can be defined as a Circle or a Rect, which have the same associated attributes (apart from image). Actors are usually the primary game objects that you move around.

GameZero.jl also includes basic geometric shapes. Rects, Circles and Lines can be used to do everything an Actor can, having the same attributes (apart from image).

This might also apply to Rect, Triangle, and Line as well.

Possible solutions:

  • Update the docs
  • Possibly create an API for how to interact with game object-like things, like Actor, Circle, etc., allowing one to set and get position, and other properties.

not working on julia 1.9

[ Info: Precompiling GameZero [9da27670-f782-11e9-1da1-f53579315bfe] ERROR: LoadError: InitError: could not load library "C:\Users\Administrator\.julia\artifacts\fa03230282478d82c2295049d440075426a17202\bin\SDL2_ima ge.dll"

Make GameZero types better and more extensible

Right now, all Game objects are concrete. However, it may be worthwhile to abstract out things right now.
Primarily, Game and Actor must be subtypes of AbstractGame and AbstractActor, which themselves can be concretised to Actor and Game. Functions which can be abstracted should be.

does not launch game window

When running the examples as described in the documentation, "basic.jl" throws the following error:

ERROR: MethodError: Cannot `convert` an object of type 
  String to an object of type 
  ARGB
Closest candidates are:
  convert(::Type{C}, ::Color, ::Any) where C<:TransparentColor at /home/jts/.julia/packages/ColorTypes/7OlxI/src/conversions.jl:78
  convert(::Type{C}, ::C) where C<:Colorant at /home/jts/.julia/packages/ColorTypes/7OlxI/src/conversions.jl:72
  convert(::Type{C}, ::Colorant) where C<:Colorant at /home/jts/.julia/packages/ColorTypes/7OlxI/src/conversions.jl:73
  ...
Stacktrace:
 [1] ARGB(x::String)
   @ ColorTypes ~/.julia/packages/ColorTypes/7OlxI/src/types.jl:528
 [2] GameZero.Screen(name::String, w::Int64, h::Int64, color::String)
   @ GameZero ~/.julia/packages/GameZero/e03cc/src/screen.jl:11
 [3] initscreen(gm::Module, name::String)
   @ GameZero ~/.julia/packages/GameZero/e03cc/src/GameZero.jl:64
 [4] initgame(jlf::String, external::Bool)
   @ GameZero ~/.julia/packages/GameZero/e03cc/src/GameZero.jl:246
 [5] rungame(jlf::String, external::Bool)
   @ GameZero ~/.julia/packages/GameZero/e03cc/src/GameZero.jl:195
 [6] rungame(jlf::String)
   @ GameZero ~/.julia/packages/GameZero/e03cc/src/GameZero.jl:194
 [7] top-level scope
   @ REPL[2]:1

"basic2.jl" warns about being unable to find ALSA libraries but otherwise simply does not launch a game window:

┌ Warning: No audio device available, sounds and music will not play.
│ ALSA: Couldn't open audio device: Aucun fichier ou dossier de ce type
└ @ GameZero ~/.julia/packages/GameZero/e03cc/src/GameZero.jl:303

versioninfo():

Julia Version 1.6.3
Commit ae8452a9e0 (2021-09-23 17:34 UTC)
Platform Info:
  OS: Linux (x86_64-unknown-linux-gnu)
  CPU: AMD Ryzen 5 5600X 6-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.0 (ORCJIT, generic)
Environment:
  JULIA_LOAD_PATH = :
  JULIA_DEPOT_PATH = :/home/jts/.guix-profiles/julia/share/julia/:/home/jts/.guix-profiles/julia/share/julia/

GameZero: 0.2.1

How to prevent clearing of the screen?

For example, I want this to result in tracing a line along w's history of positions.

function draw(g::Game)
    draw(Circle(w.x, w.y, 1), colorant"gray")
end

For me it just shows the circle moving about as determined by w's update function, while I'm expecting many little circles showing w's trajectory.

It seems in certain examples you had to clear the canvas by adding clear() or fill()? But for me I see no difference.
https://docs.juliahub.com/GameZero/tTDGf/0.2.1/examples/basic2/

function draw()
    fill(current_color)
    ...

https://docs.juliahub.com/GameZero/tTDGf/0.2.1/examples/Breakout/

function draw()
    clear()
    ...

Is what I'm asking for possible? Sorry if I'm missing something obvious, I'm fairly new to Julia.

Linux: Hyperspeed bug

There appears to be some form of timing issue when using GameZero in Linux.

As an example, it takes less than 1/2 a second for the bird in flappy bird to hit the pipe, an reset the game continuously.

I get the same blazing fast performance with the basic.jl example.

Control Render

is it possible to control render?
like user decide when to draw objects and when not to draw objects(for faster execution sometimes we don't need rendering, like while training a deep learning agent)

New Bug

i tried the code twice and it was throwing an error in both
also some times it stuck(when i'm not drawing objects, it stuck for long time), it's much slower than pygame as i expected it to be much more faster(or i've made a mistake in my code)

it may take few hours to get the error, usually between 3000-4000 episodes

using Flux
using Zygote
using Flux: gradient, params, ADAM, Momentum
using Flux.Losses: huber_loss
using Gym
using Distributions: Categorical, logpdf
using Statistics: mean, std


# ------------------------ MEMORY ---------------------------
mutable struct Memory
    states::Vector{Vector{Float32}}
    actions::Vector{Int}
    rewards::Vector{Float32}
    dones::Vector{Bool}
    log_probs::Vector{Float32}
end

function vector2matrix(input_vec::Vector{Vector{Float32}})
    nrows = length(input_vec)
    ncols = length(input_vec[1])
    matrix = zeros(Float32, ncols, nrows)
    for i  1:nrows
        matrix[:, i] = input_vec[i]
    end
    matrix
end

function matrix2vector(input_matrix)
    vector = Array{Vector{Float32}, 1}()
    for i  1:size(input_matrix, 2)
        push!(vector, input_matrix[:, i])
    end
    vector
end

function clear_memory(m::Memory)
    m.states = []
    m.actions = []
    m.rewards = []
    m.dones = []
    m.log_probs = []
end

# ------------------------- model --------------------------------
function build_networks(input_dim, output_dim, hidden_dim)
    actor = Chain(
        Dense(input_dim, hidden_dim, tanh),
        
        Dense(hidden_dim, hidden_dim, tanh),
        
        Dense(hidden_dim, output_dim),
        softmax
    )

    critic = Chain(
        Dense(input_dim, hidden_dim, tanh),
        
        Dense(hidden_dim, hidden_dim, tanh),
       
        Dense(hidden_dim, 1)
    )
    actor, critic
end

mutable struct Model
    actor::Chain
    critic::Chain
end

Flux.@functor Model

# --------------------------- agent -----------------------------

mutable struct PPO
    old_policy::Model
    policy::Model
    gamma::Float32
    update_every::Int
    update_step::Int
    opt
    memory::Memory
    eps_clip::Float32
    k_epochs::Int
    state_values::Vector{Float32}
    log_probs::Vector{Float32}
end

function PPO(state_dim::Int, action_dim::Int, hidden_dim::Int, lr, gamma, k_epochs, eps_clip, update_every, memory)
    println(state_dim, action_dim, hidden_dim)
    actor, critic = build_networks(state_dim, action_dim, hidden_dim)
    old_policy = Model(actor, critic)
    policy = Model(actor, critic)
    opt = ADAM(lr)
    update_step = 0
    state_values = [0.0]
    log_probs = [0.0]
    PPO(
        old_policy,
        policy,
        gamma,
        update_every,
        update_step,
        opt,
        memory,
        eps_clip,
        k_epochs,
        state_values,
        log_probs
    )
end

function select_action(agent::PPO, state::Vector{Float32}, train_mode::Bool)
    probs = agent.old_policy.actor(state)
    dist = Categorical(probs)
    action = rand(dist)
    if train_mode
        log_prob = logpdf(dist, action)
        push!(agent.memory.states, state)
        push!(agent.memory.actions, action)
        push!(agent.memory.log_probs, log_prob)
    end
    action
end

function take_step(agent::PPO, reward, done)
    push!(agent.memory.rewards, reward)
    push!(agent.memory.dones, done)
    agent.update_step += 1
    if agent.update_step % agent.update_every == 0
        train(agent)
        clear_memory(agent.memory)
    end
end

function update_target!(target, model; τ = 1f0)
    for (p_t, p_m) in zip(params(target), params(model))
        p_t .= (1f0 - τ) * p_t .+ τ * p_m
    end
end


function train(agent::PPO)
    states = vector2matrix(agent.memory.states)
    rewards = Array{Float32, 1}()
    discounted_reward = 0.0
    for (reward, done)  zip(reverse(agent.memory.rewards), reverse(agent.memory.dones))
        if done
            discounted_reward = 0.0
        end
        discounted_reward = reward + agent.gamma * discounted_reward
        insert!(rewards, 1, discounted_reward)
    end
    rewards = (rewards .- mean(rewards)) ./ (std(rewards) .+ 1e-5)
    
    for _  1:agent.k_epochs
        gs = gradient(params(agent.policy.critic)) do
            state_values = vec(agent.policy.critic(states))
            Zygote.ignore() do 
                agent.state_values = state_values
            end
            huber_loss(state_values, rewards)
        end
        Flux.Optimise.update!(agent.opt, params(agent.policy.critic), gs)
        
        gs = gradient(params(agent.policy.actor)) do
            

            advantages = rewards .- agent.state_values
                
            
            probs = agent.policy.actor(states)
            probs_lst = [probs[:, i] for i  1:size(probs, 2)]
            
            dist = [Categorical(x) for x  probs_lst]
            
            entropies = map(x -> -sum(x .- log.(x)), probs_lst)
            
            log_probs = logpdf.(dist, agent.memory.actions)
                
            
            ratio = exp.(log_probs .- agent.memory.log_probs)
            
            surr1 = ratio .* advantages
            surr2 = clamp.(ratio, 1 - agent.eps_clip, 1 + agent.eps_clip) .* advantages
            loss  = mean(-min.(surr1, surr2))
            loss
        end
        Flux.Optimise.update!(agent.opt, params(agent.policy.actor), gs)
    end
    update_target!(agent.old_policy.critic, agent.policy.critic)
    update_target!(agent.old_policy.actor, agent.policy.actor)

end

# ----------------------------------- train -----------------------------------

function train_loop()
    env = GymEnv("CartPole-v1")
    state_dim = env.observation_space.shape[1]
    action_dim = env.action_space.n
    memory = Memory([], [], [], [], [])
    agent = PPO(state_dim, action_dim, 128, 0.001, 0.99, 4, 0.2, 2000, memory)
    total_reward = 0
    for episode  1:100000
        state = reset!(env)
        for _  1:2000
            action = select_action(agent, state)
            state, reward, done, _ = step!(env, action - 1)
            total_reward += reward
            take_step(agent, reward, done)
            if done
                break
            end

        end

        if episode % 20 == 0
            avg_reward = total_reward / 20
            total_reward = 0
            @info "Episode : $episode | avg_reward : $avg_reward"
        end
    end
end














# -------------------------------------------- GAME ------------------------------------------------------------------------
using GameZero
using Colors


WIDTH = 400
HEIGHT = 400
WHITE = colorant"white"
BLUE = colorant"blue"
RED = colorant"red"
YELLOW = colorant"yellow"
BACKGROUND = WHITE

initial_x = 200
initial_y = 200
BLOCKSIZE = 20



mutable struct SnakeEnv
    SCORE::Int
    DIRECTION::String
    done::Bool
    state::Vector{Float32}
    reward::Float32
    allow_render::Bool
    snake::Vector{Rect}
    food::Rect
    step::Int
    use_first_state::Bool
    txt
    
end

directions_lst = ["right", "left", "up", "down"]

function place_food(snake)
    food_x = rand(1:WIDTH - BLOCKSIZE)
    food_y = rand(1:HEIGHT - BLOCKSIZE)

    food_obj = Rect(food_x, food_y, BLOCKSIZE, BLOCKSIZE)
    if any(map(x -> collide(x, food_obj), snake))
        place_food(snake)
    end
    food_obj
end


function get_state_1(env::SnakeEnv)
    danger_right_1, danger_left_1, danger_up_1, danger_down_1 = check_danger(env, 1)
    danger_right_2, danger_left_2, danger_up_2, danger_down_2 = check_danger(env, 2)
    danger_right_3, danger_left_3, danger_up_3, danger_down_3 = check_danger(env, 3)
    danger_right_4, danger_left_4, danger_up_4, danger_down_4 = check_danger(env, 4)
    state = [danger_right_1, danger_left_1, danger_up_1, danger_down_1,
             danger_right_2, danger_left_2, danger_up_2, danger_down_2,
             danger_right_3, danger_left_3, danger_up_3, danger_down_3,
             danger_right_4, danger_left_4, danger_up_4, danger_down_4]
    
    head = env.snake[1]
    tail = env.snake[end]
    food = env.food

    head.x > food.x ? push!(state, 1) : push!(state, 0)
    head.y > food.y ? push!(state, 1) : push!(state, 0)
    tail.x > food.x ? push!(state, 1) : push!(state, 0)
    tail.y > food.y ? push!(state, 1) : push!(state, 0)
    head.x > tail.x ? push!(state, 1) : push!(state, 0)
    head.y > tail.y ? push!(state, 1) : push!(state, 0)
    
    # add directions
    for dir  directions_lst
        dir == env.DIRECTION ? push!(state, 1.0) : push!(state, 0.0)
    end
    env.state = state

end

function get_state_2(env::SnakeEnv)
    danger_right_1, danger_left_1, danger_up_1, danger_down_1 = check_danger(env, 1)
    head = env.snake[1]
    mid = env.snake[Int(round(length(env.snake) / 2))]
    tail = env.snake[end]
    food = env.food
    dir = findfirst(x -> x == env.DIRECTION, directions_lst)[1]
    state = [ mid.x / WIDTH, mid.y / HEIGHT, length(env.snake) / WIDTH,
             head.x / WIDTH, head.y / HEIGHT, tail.x / WIDTH, tail.y / HEIGHT, 
             (head.x - food.x) / WIDTH, (head.y - food.y) / HEIGHT, (tail.x - food.x) / WIDTH, (tail.y - food.y) / HEIGHT,
             food.x / WIDTH, food.y / HEIGHT,
             dir / 4]
            
    env.state = state
end

function reset(env::SnakeEnv)
    env.snake = [Rect(initial_x, initial_y, BLOCKSIZE, BLOCKSIZE),
         Rect(initial_x - BLOCKSIZE, initial_y, BLOCKSIZE, BLOCKSIZE),
         Rect(initial_x - 2 * BLOCKSIZE, initial_y, BLOCKSIZE, BLOCKSIZE)]
    
    env.food = place_food(env.snake)
    env.done = false
    env.reward = 0
    env.step = 1
    env.SCORE = 0
    env.DIRECTION = "right"
    env.txt = TextActor("Score : $(env.SCORE)", "moonhouse")
    if env.use_first_state
        get_state_1(env)
    else
        get_state_2(env)
    end
end


function draw_objects(env::SnakeEnv)
    head = env.snake[1]
    body = env.snake[2:end]
    draw(head, YELLOW, fill=true)
    map(x -> draw(x, BLUE), body)
    draw(env.food, RED, fill=true)
    draw(env.txt)

end

function game_over(env::SnakeEnv)
    head = env.snake[1]
    
    if head.x > WIDTH - BLOCKSIZE || head.x < 0 || head.y > HEIGHT - BLOCKSIZE || head.y < 0
       return true, -10
    end

    if env.step > 30 * length(env.snake)
        return true, -10
    end
    
    if any(map(x -> collide(x, head), env.snake[3:end]))
        return true, -100
    end

    

    return false, 0
end

function check_danger(env::SnakeEnv, step_size::Int)
    head = env.snake[1]
    danger_right = env.DIRECTION == "right" && (head.x + step_size * BLOCKSIZE > WIDTH - BLOCKSIZE) ? 1.0 : 0.0
    danger_left =  env.DIRECTION == "left" && (head.x - step_size * BLOCKSIZE) < 0 ? 1.0 : 0.0
    danger_up =  env.DIRECTION == "up" && (head.y - step_size * BLOCKSIZE) < 0 ? 1.0 : 0.0
    danger_up_down =  env.DIRECTION == "down" && (head.y + step_size * BLOCKSIZE) > HEIGHT - BLOCKSIZE ? 1.0 : 0.0

    danger_right, danger_left, danger_up, danger_up_down
 end



function move_snake(env::SnakeEnv)
        
    h_x = env.snake[1].x
    h_y = env.snake[1].y
    
    if env.DIRECTION == "right"
        insert!(env.snake, 1, Rect(h_x + BLOCKSIZE, h_y, BLOCKSIZE, BLOCKSIZE))
    elseif env.DIRECTION == "left"
        insert!(env.snake, 1, Rect(h_x - BLOCKSIZE, h_y, BLOCKSIZE, BLOCKSIZE))
    elseif env.DIRECTION == "up"
        insert!(env.snake, 1, Rect(h_x, h_y - BLOCKSIZE, BLOCKSIZE, BLOCKSIZE))
    else
        insert!(env.snake, 1,  Rect(h_x, h_y + BLOCKSIZE, BLOCKSIZE, BLOCKSIZE))
    end
    
end

function step(env::SnakeEnv, action::Int)
    env.step += 1
    if action == 1 && env.DIRECTION != "up"
        env.DIRECTION = "down"
    elseif action == 2 && env.DIRECTION != "down"
        env.DIRECTION = "up"
    elseif action == 3 && env.DIRECTION != "left"
        env.DIRECTION = "right"
    elseif action == 4 && env.DIRECTION != "right"
        env.DIRECTION = "left"
    end

    # update snake position
    move_snake(env)
    # check game over
    env.done, env.reward = game_over(env)
    if env.done
        if env.use_first_state
            get_state_1(env)
        else
            get_state_2(env)
        end
        return env.state, env.reward, env.done, env.SCORE
    end


    if collide(env.snake[1], env.food)
        env.SCORE += 1
        env.food = place_food(env.snake)
        env.reward = 10
    else
        pop!(env.snake)
    end
    env.txt = TextActor("Score : $(env.SCORE)", "moonhouse")
    
    if env.use_first_state
        get_state_1(env)
    else
        get_state_2(env)
    end
    return env.state, env.reward, env.done, env.SCORE
end



# -------------------- CREATE ENV ---------------------------------
snake_env = [Rect(initial_x, initial_y, BLOCKSIZE, BLOCKSIZE),
Rect(initial_x - BLOCKSIZE, initial_y, BLOCKSIZE, BLOCKSIZE),
Rect(initial_x - 2 * BLOCKSIZE, initial_y, BLOCKSIZE, BLOCKSIZE)]

food_env = place_food(snake_env)


env = SnakeEnv(0, "right", false, [0.0], 0.0, true, snake_env, food_env, 1, true, TextActor("Score : 0", "moonhouse"))
reset(env)
state_dim = length(env.state)
action_dim = 4

memory = Memory([], [], [], [], [])
agent = PPO(state_dim, action_dim, 128, 0.001, 0.99, 4, 0.2, 2000, memory)

function draw(g::Game)
    if env.allow_render
        sleep(0.03)
        draw_objects(env)
    end
    
end





# ---------------------------- loop ------------------------------

episode = 0
total_reward = 0
record = 0
function print_info(episode, total_reward, record)
        env.allow_render = true
        avg_reward = total_reward / 20
        println("Episode : $episode | avg_reward : $avg_reward | record : $record")
end

function onetime_loop()
    action = select_action(agent, env.state, false)
        
    next_state, reward, done, SCORE = step(env, action)
   
    
    if done
        env.allow_render = false
        reset(env)
    end
end

function full_loop()
    global episode, total_reward, record
    
    while !env.done
        
        action = select_action(agent, env.state, true)
        
        next_state, reward, done, SCORE = step(env, action)
        take_step(agent, reward, done)
        total_reward += reward
    end
    
    episode += 1
    if episode % 20 == 0
        
        print_info(episode, total_reward, record)
        total_reward = 0
    else
        env.allow_render =  false
    end

    if env.SCORE > record
        record = env.SCORE
    end
    reset(env)
    
end

function update(g::Game)
    env.allow_render ? onetime_loop() : full_loop()
end

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x6d642194 -- TTF_SizeUTF8_Internal at /workspace/srcdir/SDL2_ttf-2.0.15\SDL_ttf.c:1185
in expression starting at REPL[2]:1
TTF_SizeUTF8_Internal at /workspace/srcdir/SDL2_ttf-2.0.15\SDL_ttf.c:1185
TTF_RenderUTF8_Blended at /workspace/srcdir/SDL2_ttf-2.0.15\SDL_ttf.c:1630
TTF_RenderText_Blended at /workspace/srcdir/SDL2_ttf-2.0.15\SDL_ttf.c:1600
TTF_RenderText_Blended at C:\Users\Administrator.julia\packages\SimpleDirectMediaLayer\wjMsP\src\LibSDL2.jl:6038 [inlined]
#TextActor#12 at C:\Users\Administrator.julia\packages\GameZero\q74y7\src\actor.jl:35
TextActor at C:\Users\Administrator.julia\packages\GameZero\q74y7\src\actor.jl:33 [inlined]
step at C:\Users\Administrator\Desktop\julia\snake.jl:445
full_loop at C:\Users\Administrator\Desktop\julia\snake.jl:515
update at C:\Users\Administrator\Desktop\julia\snake.jl:537
unknown function (ip: 0000022c242fc776)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: UNKNOWN at 0x7ffdd3cc49b9 --

Better circle drawing algorithm

The current algorithm for drawing circles is not very good (though it is fast). It looks pretty ugly if the cirle is more than a about 10 pixels in diameter.

image

CPU is being highly used.

First of all, I apologize if this is not an issue.

I noticed that whenever the actor is running, the cpu starts being used and it reaches 25% which causes a drop in the framerates. I am not sure if changing the image of the actor causes this. I tried turning off animations() to check if the other animations in the environment like the platform and the plants were causing it. It was not that. So my thoughts noticing that pattern was that looping and changing images in a fast way, causes this. I am not sure if this is normal or maybe it is an issue. Thank you.

The images are here.
images.zip

This is how the game looks.
The assets are not mine. Author: https://maaot.itch.io/mossy-cavern
Screenshot_1

function update(g::Game)

    bring_back()
    gravity()
    animations()
    #####################
    #WALKING AND RUNNING#
    #####################

    global STEP, IDLE, VELOCITY, LOOKING_AT

    if g.keyboard.LCTRL && g.keyboard.D #RUNNING TO THE RIGHT SIDE
        LOOKING_AT = 0
        VELOCITY = 0
        if VELOCITY < 50
            VELOCITY += 1
        end
        STEP += 1
        witch.image = "wr$(STEP).png"
        witch.x += 3
        witch.image = "wr$(STEP).png"
        if STEP == 18
            STEP = 1
        end

    elseif g.keyboard.LCTRL && g.keyboard.A #RUNNING TO THE LEFT SIDE
        LOOKING_AT = 1
        VELOCITY = 0
        if VELOCITY < 5
            VELOCITY += 1
        end
        STEP += 1
        witch.image = "wr$(STEP).png"
        witch.x -= 3
        witch.image = "wl$(STEP).png"
        if STEP == 18
            STEP = 1
        end

    elseif g.keyboard.A 

        LOOKING_AT = 1
        VELOCITY += 2
        STEP += 1
        witch.image = "wl$(STEP).png"
        witch.x -= 2
        if STEP == 18
            STEP = 1
        end

    elseif g.keyboard.D
        LOOKING_AT = 0
        VELOCITY += 2
        STEP += 1
        witch.image = "wr$(STEP).png"
        witch.x += 2
        if STEP == 18
            STEP = 1
        end
    else

        ################
        #IDLE ANIMATION#
        ################
        
        LOOKING_AT = 2 #LOOKING AT CENTER

        IDLE += 0.35

        witch.image = "i$(round(Int, IDLE)).png"

        if round(Int, IDLE) == 18
            IDLE = 1
        end
        VELOCITY = 0

    end
end

Gamepad Controller Support

I'm curious if theres any plan to put in gamepad support, given its SDL2 it should be doable I assume?

Built in Physics System

I suggest that work should be started on making a built in physics system.
There are several bindings for things like chipmunk that could be used, but I propose that we could build one for GameZero. I have found the beginnings of a Julia Physics System called Matter.jl that could be used to do this.

Error Actor

a=Actor("/home/jmarcellopereira/images/bloco.png");
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getproperty at ./Base.jl:33 [inlined]
[2] getindex at ./refvalue.jl:32 [inlined]
[3] file_path(::String, ::Symbol) at /home/jmarcellopereira/.julia/packages/GameZero/QdBGK/src/resources.jl:45
[4] image_surface(::String) at /home/jmarcellopereira/.julia/packages/GameZero/QdBGK/src/resources.jl:36
[5] Actor(::String; kv::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/jmarcellopereira/.julia/packages/GameZero/QdBGK/src/actor.jl:18
[6] Actor(::String) at /home/jmarcellopereira/.julia/packages/GameZero/QdBGK/src/actor.jl:18
[7] top-level scope at REPL[2]:1

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

Unicode Chinese Characters (ttf) are not being shown

#sf = SDL2.TTF_RenderText_Blended(font, text, SDL2.Color(color...))
sf = SDL2.TTF_RenderUTF8_Blended(font, text, SDL2.Color(color...))

Following Aviks suggestion as above ...

Chinese Characters can be shown correctly
SnakeZero_01
SnakeZero_02

Will GZ.jl eventually be able to do multiple files in a project?

So I was trying to organize a game and I wanted to split it up in multiple files but then I realized after many errors that GameZero can't do multiple files (I think it can't I am not entirely sure but if it is true it can't do multiple files please consider making it able to because it would make productivity a lot better and less messy).

Unicode Chinese Characters (ttf) are not being shown

if gameover == false
    display = "分數(Score) = $score"
else
    display = "GAME OVER! Final Score = $score"
    #play again instructions
    replay = TextActor("Click to play Again,  點擊...再玩", sDspFont; font_size = 26, color = Int[0, 0, 0, 255])
    replay.pos = (135, 390)
    draw(replay)
end

above Chinese Character are not being shown
title_01

Impossible to include other files in the game

It would be great to have 1 file that contains the game and include other files that contains the structs created in the game.

I was tring to make a game.jl that had "include(snake.jl)".

In game.jl, all the loops and conditions would be verified, while the snake.jl file would have the definition of the struct snake and its methods. But when i try to do "include(snake.jl)" I get "LoadError: UndefVarError: include not defined".

Apperantly, there's no function "include" in gamezero, or it erases the base function from julia. I don't uderstand exactly

Unknown key value throws error

Games crash when pressing a key that is not in Keys.Key, for example non-english characters (here ù) or special keys (like volume up)

julia> rungame("GZExamples\\Spaceship\\Spaceship.jl")
┌ Warning: Use lowercases names for resource files. It is safer when moving between windows and unix: Space_pod.png
└ @ GameZero C:\Users\user\.julia\packages\GameZero\QdBGK\src\resources.jl:103
┌ Error: ArgumentError("invalid value for Enum Key: 249")
│   exception =
│    ArgumentError: invalid value for Enum Key: 249
│    Stacktrace:
│      [1] enum_argument_error(typename::Symbol, x::UInt32)
│        @ Base.Enums .\Enums.jl:79
│      [2] Key
│        @ .\Enums.jl:192 [inlined]
│      [3] handleKeyPress(g::Game, e::Vector{UInt8}, t::UInt32)
│        @ GameZero ~\.julia\packages\GameZero\QdBGK\src\GameZero.jl:143
│      [4] handleEvents!
│        @ ~\.julia\packages\GameZero\QdBGK\src\GameZero.jl:126 [inlined]
│      [5] mainloop(g::Game)
│        @ GameZero ~\.julia\packages\GameZero\QdBGK\src\GameZero.jl:95
│      [6] rungame(jlf::String)
│        @ GameZero ~\.julia\packages\GameZero\QdBGK\src\GameZero.jl:186
│      [7] top-level scope
│        @ REPL[25]:1
│      [8] eval(m::Module, e::Any)
│        @ Core .\boot.jl:360
│      [9] eval_user_input(ast::Any, backend::REPL.REPLBackend)
│        @ REPL C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\REPL.jl:139
│     [10] repl_backend_loop(backend::REPL.REPLBackend)
│        @ REPL C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\REPL.jl:200
│     [11] start_repl_backend(backend::REPL.REPLBackend, consumer::Any)
│        @ REPL C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\REPL.jl:185
│     [12] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool)
│        @ REPL C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\REPL.jl:317
│     [13] run_repl(repl::REPL.AbstractREPL, consumer::Any)
│        @ REPL C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\REPL.jl:305
│     [14] (::Base.var"#878#880"{Bool, Bool, Bool})(REPL::Module)
│        @ Base .\client.jl:387
│     [15] #invokelatest#2
│        @ .\essentials.jl:707 [inlined]
│     [16] invokelatest
│        @ .\essentials.jl:706 [inlined]
│     [17] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
│        @ Base .\client.jl:372
│     [18] exec_options(opts::Base.JLOptions)
│        @ Base .\client.jl:302
│     [19] _start()
│        @ Base .\client.jl:485
└ @ GameZero C:\Users\user\.julia\packages\GameZero\QdBGK\src\GameZero.jl:189

ALSA bug

Hi, I'm getting this error:

julia> go()
ALSA lib conf.c:4133:(snd_config_update_r) Cannot access file /workspace/destdir/share/alsa/alsa.conf
ALSA lib conf.c:4133:(snd_config_update_r) Cannot access file /workspace/destdir/share/alsa/alsa.conf
ALSA lib pcm.c:2660:(snd_pcm_open_noupdate) Unknown PCM default
┌ Warning: No audio device available, sounds and music will not play.
│ ALSA: Couldn't open audio device: No such file or directory
└ @ GameZero ~/.julia/packages/GameZero/JN07Y/src/GameZero.jl:292
ALSA lib conf.c:4133:(snd_config_update_r) Cannot access file /workspace/destdir/share/alsa/alsa.conf
ALSA lib conf.c:4133:(snd_config_update_r) Cannot access file /workspace/destdir/share/alsa/alsa.conf

I don't understand how GZ connects to ALSA, but of course there's no /workspace directory on my system. Sound works fine outside of this. Here's my sound setup:

➤ inxi -xxA
Audio:     Device-1: Advanced Micro Devices [AMD] Family 17h HD Audio vendor: Gigabyte driver: snd_hda_intel v: kernel 
           bus-ID: 0a:00.3 chip-ID: 1022:1457 
           Device-2: NVIDIA TU102 High Definition Audio vendor: ASUSTeK driver: snd_hda_intel v: kernel bus-ID: 41:00.1 
           chip-ID: 10de:10f7 
           Device-3: Logitech C922 Pro Stream Webcam type: USB driver: snd-usb-audio,uvcvideo bus-ID: 1-1:2 chip-ID: 046d:085c 
           Device-4: Logitech Blue Microphones type: USB driver: hid-generic,snd-usb-audio,usbhid bus-ID: 1-3:3 
           chip-ID: 046d:0ab7 
           Device-5: Valve Valve VR Radio type: USB driver: cdc_acm,hid-generic,usbhid bus-ID: 3-1.3.2:8 chip-ID: 28de:2102 
           Device-6: Valve Valve VR Radio & HMD Mic type: USB driver: hid-generic,snd-usb-audio,usbhid bus-ID: 3-1.3.3:9 
           chip-ID: 28de:2102 
           Sound Server-1: ALSA v: k5.10.49-1-MANJARO running: yes 
           Sound Server-2: sndio v: N/A running: no 
           Sound Server-3: JACK v: 1.9.18 running: no 
           Sound Server-4: PulseAudio v: 14.2 running: no 
           Sound Server-5: PipeWire v: 0.3.31 running: yes 

Too many open files error

Base.IOError("readdir(\"./images\"): too many open files (EMFILE)", -24)

I made my own version of the flappy bird game, and I face this issue if I play it for a while. It looks like GameZero is not GC-ing some images(?)

Note, I change the bird image everytime I press space, and for a game like flappy bird, that is quite often. I thought the image will be reused?

Better way to run game

We currently suggest users start the Julia repl to run the game. We should provide shell and cmd scripts to run games to make it easier to start from the shell.

At the same time, we should find a better way to start a game programatically, that plays well with modules and include

Game doesn't run without a draw function

it should display an empty frame if a draw function has not been defined

julia> rungame("MyGame.jl")
ERROR: BoundsError: attempt to access 0-element Array{Method,1} at index [1]
Stacktrace:
 [1] getindex at .\array.jl:809 [inlined]
 [2] getfn(::Module, ::Symbol, ::Int64) at C:\Users\avik\dev\GameZero\src\GameZero.jl:239
 [3] initgame(::String) at C:\Users\avik\dev\GameZero\src\GameZero.jl:219
 [4] rungame(::String) at C:\Users\avik\dev\GameZero\src\GameZero.jl:183
 [5] top-level scope at REPL[32]:1

`actor.right` is incorrect ?

While trying out Flappy Bird and tinkering with it, I stumbled accross some strange things.

we have actor.right < actor.left:

(pipe_top.right, pipe_top.left) = (228, 328)
(pipe_top.right, pipe_top.left) = (225, 325)
(pipe_top.right, pipe_top.left) = (222, 322)

it seems like right is computed as left - width. shouldn't it be left + width or am I missing something ?

getPos(::Val{:left}, s::Rect) = s.x
getPos(::Val{:right}, s::Rect) = s.x-s.w
getPos(::Val{:top}, s::Rect) = s.y
getPos(::Val{:bottom}, s::Rect) = s.y-s.h

EDIT: same thing for bottom

Crash on `rungame`

julia> rungame("basic.jl")
libGL error: MESA-LOADER: failed to open iris: /home/miguel/bin/julia-1.6.2/bin/../lib/julia/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /usr/lib/dri/iris_dri.so) (search paths /usr/lib/dri)
libGL error: failed to load driver: iris
libGL error: MESA-LOADER: failed to open iris: /home/miguel/bin/julia-1.6.2/bin/../lib/julia/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /usr/lib/dri/iris_dri.so) (search paths /usr/lib/dri)
libGL error: failed to load driver: iris
libGL error: MESA-LOADER: failed to open swrast: /home/miguel/bin/julia-1.6.2/bin/../lib/julia/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /usr/lib/dri/swrast_dri.so) (search paths /usr/lib/dri)
libGL error: failed to load driver: swrast
X Error:  BadValue
  Request Major code 152 (GLX)
  Request Minor code 3 ()
  Value 0x0
  Error Serial #103
  Current Serial #104
~ $
  • Arch Linux, up to date as of today.
  • Intel IceLake i5 with Iris graphics.
  • Julia 1.6.2

This looks to me like an incompatibility between Julia's bundled libstdc++ and my system drivers. Is there a way to make GameZero use my system's libstdc++?

Graphics not properly scaled on high dpi screen on Mac

I tested basic.jl and found that the graphics are only shown in the top-left quadrant of the window on my Mac. I guess high DPI (retina) screen is not supported. The background image is shown correctly maybe because it is a texture that fills the whole surface.

I see some code which may be related to high DPI screen in window.jl but I have no idea how to fix it...

The same issue exists in all the other examples (basic2.jl and ones in GZExamples).

basic_mac.mov

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.