Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upUncaught TypeError: Cannot read property 'ctor' of undefined #167
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
Here is the full code of the little project that's causing this:
Model.elm
module Shooter.Model where
import Array (..)
----------
-- MATH --
----------
type alias Point =
{ x : Float
, y : Float
}
add : Point -> Point -> Point
add p q =
Point (p.x + q.x) (p.y + q.y)
square : Float -> Float
square x = x * x
distanceSquared : Point -> Point -> Float
distanceSquared p q =
square (p.x - q.x) + square (p.y - q.y)
distance : Point -> Point -> Float
distance p q =
sqrt (distanceSquared p q)
------------
-- ENTITY --
------------
type alias Entity a =
{ a | position : Point
, velocity : Point
, radius : Float
}
collide : Entity a -> Entity b -> Bool
collide entity1 entity2 =
square (entity1.radius + entity2.radius) <=
distanceSquared entity1.position entity2.position
move : Entity a -> Entity a
move entity =
{ entity | position <- entity.position `add` entity.velocity }
setVelocity : Point -> Entity a -> Entity a
setVelocity velocity entity =
{ entity | velocity <- velocity }
-------------------
-- GAME ENTITIES --
-------------------
type alias Bullet = Entity { attack : Int }
type alias Ship a =
Entity { a | health : Int
, maxHealth : Int }
type alias Hero = Ship {}
hero : Hero
hero =
{ position = Point 200 10
, velocity = Point 0 0
, radius = 20
, health = 10
, maxHealth = 10
}
type alias Enemy = Ship {}
enemy : Enemy
enemy =
{ position = Point 200 300
, velocity = Point 0 0
, radius = 20
, health = 1
, maxHealth = 1
}
type alias GameState =
{ hero : Hero
, enemies : Array Enemy
, bullets : Array Bullet
}
gameState : GameState
gameState =
{ hero = hero
, enemies = push enemy empty
, bullets = empty
}
isAlive : Ship a -> Bool
isAlive ship =
ship.health > 0
hit : Bullet -> Ship a -> Ship a
hit bullet ship =
{ ship | health <- ship.health - bullet.attack }
createHeroBullet : Hero -> Int -> Bullet
createHeroBullet hero attack =
let bulletStartingPosition =
hero.position `add` Point 0 ((hero.radius / 2) + 2)
bulletVelocity =
Point 0 2
bulletRadius =
5 * attack
in
{ position = bulletStartingPosition
, velocity = bulletVelocity
, radius = bulletRadius
, attack = attack
}
createEnemyBullet : Enemy -> Int -> Bullet
createEnemyBullet enemy attack =
let bulletStartingPosition =
enemy.position `add` Point 0 -((enemy.radius / 2) + 2)
bulletVelocity =
Point 0 -2
bulletRadius =
5 * attack
in
{ position = bulletStartingPosition
, velocity = bulletVelocity
, radius = bulletRadius
, attack = attack
}Input.elm
module Shooter.Input where
import Shooter.Model (..)
import Keyboard
import Signal (..)
import Time (..)
type alias Input =
{ arrows : Point
, space : Bool
}
toInput : { x : Int, y : Int} -> Bool -> Input
toInput arrows space =
{ arrows =
{ x = toFloat arrows.x
, y = toFloat arrows.y
}
, space = space
}
userInput : Signal Input
userInput =
map2 toInput Keyboard.arrows Keyboard.space
timeDelta : Signal Time
timeDelta =
fps 60
Render.elm
module Shooter.Render where
import Graphics.Element (..)
import Graphics.Collage (..)
import Color (..)
import Shooter.Model as Model
import Array (..)
renderHero : Model.Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled blue <|
circle hero.radius
renderEnemy : Model.Enemy -> Form
renderEnemy enemy =
move (enemy.position.x, enemy.position.y) <|
filled red <|
circle enemy.radius
renderBullet : Model.Bullet -> Form
renderBullet bullet =
move (bullet.position.x, bullet.position.y) <|
filled green <|
circle bullet.radius
render : Model.GameState -> Element
render game =
let enemyForms =
map renderEnemy game.enemies
bulletForms =
map renderBullet game.bullets
heroForm =
renderHero game.hero
in
collage 400 400
(toList
(push heroForm (enemyForms `append` bulletForms)))Update.elm
module Shooter.Update where
import Shooter.Input (..)
import Shooter.Model (..)
import Array (..)
pipe : (a -> b -> b) -> Array a -> b -> b
pipe f array b =
case get 0 array of
Nothing -> b
Just a ->
pipe f (slice 1 (length array) array) (f a b)
update : Input -> GameState -> GameState
update input game =
let bullets =
if input.space == True
then
push (createHeroBullet game.hero 1) game.bullets
else
game.bullets
heroVelocity =
input.arrows
applyBullets entity =
pipe hit
(filter (collide entity) game.bullets)
entity
hero =
setVelocity heroVelocity
(move
(applyBullets game.hero))
enemies =
map move
(filter isAlive
(map applyBullets game.enemies))
in
{ game | hero <- hero
, enemies <- enemies
, bullets <- bullets
}Shooter.elm (the main file)
import Shooter.Model (..)
import Shooter.Input (..)
import Shooter.Update (..)
import Shooter.Render (..)
import Signal (..)
main =
map render
(foldp update gameState userInput)
|
Here is the full code of the little project that's causing this: Model.elm module Shooter.Model where
import Array (..)
----------
-- MATH --
----------
type alias Point =
{ x : Float
, y : Float
}
add : Point -> Point -> Point
add p q =
Point (p.x + q.x) (p.y + q.y)
square : Float -> Float
square x = x * x
distanceSquared : Point -> Point -> Float
distanceSquared p q =
square (p.x - q.x) + square (p.y - q.y)
distance : Point -> Point -> Float
distance p q =
sqrt (distanceSquared p q)
------------
-- ENTITY --
------------
type alias Entity a =
{ a | position : Point
, velocity : Point
, radius : Float
}
collide : Entity a -> Entity b -> Bool
collide entity1 entity2 =
square (entity1.radius + entity2.radius) <=
distanceSquared entity1.position entity2.position
move : Entity a -> Entity a
move entity =
{ entity | position <- entity.position `add` entity.velocity }
setVelocity : Point -> Entity a -> Entity a
setVelocity velocity entity =
{ entity | velocity <- velocity }
-------------------
-- GAME ENTITIES --
-------------------
type alias Bullet = Entity { attack : Int }
type alias Ship a =
Entity { a | health : Int
, maxHealth : Int }
type alias Hero = Ship {}
hero : Hero
hero =
{ position = Point 200 10
, velocity = Point 0 0
, radius = 20
, health = 10
, maxHealth = 10
}
type alias Enemy = Ship {}
enemy : Enemy
enemy =
{ position = Point 200 300
, velocity = Point 0 0
, radius = 20
, health = 1
, maxHealth = 1
}
type alias GameState =
{ hero : Hero
, enemies : Array Enemy
, bullets : Array Bullet
}
gameState : GameState
gameState =
{ hero = hero
, enemies = push enemy empty
, bullets = empty
}
isAlive : Ship a -> Bool
isAlive ship =
ship.health > 0
hit : Bullet -> Ship a -> Ship a
hit bullet ship =
{ ship | health <- ship.health - bullet.attack }
createHeroBullet : Hero -> Int -> Bullet
createHeroBullet hero attack =
let bulletStartingPosition =
hero.position `add` Point 0 ((hero.radius / 2) + 2)
bulletVelocity =
Point 0 2
bulletRadius =
5 * attack
in
{ position = bulletStartingPosition
, velocity = bulletVelocity
, radius = bulletRadius
, attack = attack
}
createEnemyBullet : Enemy -> Int -> Bullet
createEnemyBullet enemy attack =
let bulletStartingPosition =
enemy.position `add` Point 0 -((enemy.radius / 2) + 2)
bulletVelocity =
Point 0 -2
bulletRadius =
5 * attack
in
{ position = bulletStartingPosition
, velocity = bulletVelocity
, radius = bulletRadius
, attack = attack
}Input.elm module Shooter.Input where
import Shooter.Model (..)
import Keyboard
import Signal (..)
import Time (..)
type alias Input =
{ arrows : Point
, space : Bool
}
toInput : { x : Int, y : Int} -> Bool -> Input
toInput arrows space =
{ arrows =
{ x = toFloat arrows.x
, y = toFloat arrows.y
}
, space = space
}
userInput : Signal Input
userInput =
map2 toInput Keyboard.arrows Keyboard.space
timeDelta : Signal Time
timeDelta =
fps 60
Render.elm module Shooter.Render where
import Graphics.Element (..)
import Graphics.Collage (..)
import Color (..)
import Shooter.Model as Model
import Array (..)
renderHero : Model.Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled blue <|
circle hero.radius
renderEnemy : Model.Enemy -> Form
renderEnemy enemy =
move (enemy.position.x, enemy.position.y) <|
filled red <|
circle enemy.radius
renderBullet : Model.Bullet -> Form
renderBullet bullet =
move (bullet.position.x, bullet.position.y) <|
filled green <|
circle bullet.radius
render : Model.GameState -> Element
render game =
let enemyForms =
map renderEnemy game.enemies
bulletForms =
map renderBullet game.bullets
heroForm =
renderHero game.hero
in
collage 400 400
(toList
(push heroForm (enemyForms `append` bulletForms)))Update.elm module Shooter.Update where
import Shooter.Input (..)
import Shooter.Model (..)
import Array (..)
pipe : (a -> b -> b) -> Array a -> b -> b
pipe f array b =
case get 0 array of
Nothing -> b
Just a ->
pipe f (slice 1 (length array) array) (f a b)
update : Input -> GameState -> GameState
update input game =
let bullets =
if input.space == True
then
push (createHeroBullet game.hero 1) game.bullets
else
game.bullets
heroVelocity =
input.arrows
applyBullets entity =
pipe hit
(filter (collide entity) game.bullets)
entity
hero =
setVelocity heroVelocity
(move
(applyBullets game.hero))
enemies =
map move
(filter isAlive
(map applyBullets game.enemies))
in
{ game | hero <- hero
, enemies <- enemies
, bullets <- bullets
}Shooter.elm (the main file) import Shooter.Model (..)
import Shooter.Input (..)
import Shooter.Update (..)
import Shooter.Render (..)
import Signal (..)
main =
map render
(foldp update gameState userInput)
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
I have a sneaking suspicion that it has to do with me using Arrays alongside all this collage stuff... I'm not sure... I have to further investigate
|
I have a sneaking suspicion that it has to do with me using Arrays alongside all this collage stuff... I'm not sure... I have to further investigate |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
Same bug, smaller code:
Model.elm
module Platformer.Model where
import Array (..)
type alias Point =
{ x : Float
, y : Float
}
type alias Entity a =
{ a | position : Point
, velocity : Point
, dimensions : Point
}
type alias Hero =
Entity { isGrounded : Bool }
hero : Hero
hero =
{ position = Point 0 0
, velocity = Point 0 0
, dimensions = Point 10 10
, isGrounded = True
}
type alias Platform =
Entity {}
type alias Game =
{ hero : Hero
, platforms : Array Platform
}
game : Game
game =
{ hero = hero
, platforms = empty
}Render.elm
module Platformer.Render where
import Platformer.Model (Game, Hero, Platform)
import Graphics.Collage (..)
import Graphics.Element (..)
import Color (..)
import Array (..)
renderHero : Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled green <|
rect hero.dimensions.x hero.dimensions.y
renderPlatform : Platform -> Form
renderPlatform platform =
move (platform.position.x, platform.position.y) <|
filled blue <|
rect platform.dimensions.x platform.dimensions.y
render : Game -> Element
render game =
collage 400 400
(toList
(push (renderHero game.hero)
(map renderPlatform game.platforms)))
Platformer.elm
import Platformer.Model (..)
import Platformer.Render (..)
main = render game|
Same bug, smaller code: Model.elm module Platformer.Model where
import Array (..)
type alias Point =
{ x : Float
, y : Float
}
type alias Entity a =
{ a | position : Point
, velocity : Point
, dimensions : Point
}
type alias Hero =
Entity { isGrounded : Bool }
hero : Hero
hero =
{ position = Point 0 0
, velocity = Point 0 0
, dimensions = Point 10 10
, isGrounded = True
}
type alias Platform =
Entity {}
type alias Game =
{ hero : Hero
, platforms : Array Platform
}
game : Game
game =
{ hero = hero
, platforms = empty
}Render.elm module Platformer.Render where
import Platformer.Model (Game, Hero, Platform)
import Graphics.Collage (..)
import Graphics.Element (..)
import Color (..)
import Array (..)
renderHero : Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled green <|
rect hero.dimensions.x hero.dimensions.y
renderPlatform : Platform -> Form
renderPlatform platform =
move (platform.position.x, platform.position.y) <|
filled blue <|
rect platform.dimensions.x platform.dimensions.y
render : Game -> Element
render game =
collage 400 400
(toList
(push (renderHero game.hero)
(map renderPlatform game.platforms)))
Platformer.elm import Platformer.Model (..)
import Platformer.Render (..)
main = render game |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Feb 11, 2015
Member
Is it possible to get it down to one file? To properly debug, it's best if we can get it down to as small as possible. Have we gotten there?
|
Is it possible to get it down to one file? To properly debug, it's best if we can get it down to as small as possible. Have we gotten there? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
Interesting, when you switch to lists, everything works. So my suspicion seems warranted.
Model.elm
module Platformer.Model where
import List (..)
type alias Point =
{ x : Float
, y : Float
}
type alias Entity a =
{ a | position : Point
, velocity : Point
, dimensions : Point
}
type alias Hero =
Entity { isGrounded : Bool }
hero : Hero
hero =
{ position = Point 0 0
, velocity = Point 0 0
, dimensions = Point 10 10
, isGrounded = True
}
type alias Platform =
Entity {}
type alias Game =
{ hero : Hero
, platforms : List Platform
}
game : Game
game =
{ hero = hero
, platforms = []
}Render.elm
module Platformer.Render where
import Platformer.Model (Game, Hero, Platform)
import Graphics.Collage (..)
import Graphics.Element (..)
import Color (..)
import List (..)
renderHero : Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled green <|
rect hero.dimensions.x hero.dimensions.y
renderPlatform : Platform -> Form
renderPlatform platform =
move (platform.position.x, platform.position.y) <|
filled blue <|
rect platform.dimensions.x platform.dimensions.y
render : Game -> Element
render game =
collage 400 400
((::) (renderHero game.hero)
(map renderPlatform game.platforms))
Platformer.elm
import Platformer.Model (..)
import Platformer.Render (..)
main = render game|
Interesting, when you switch to lists, everything works. So my suspicion seems warranted. Model.elm module Platformer.Model where
import List (..)
type alias Point =
{ x : Float
, y : Float
}
type alias Entity a =
{ a | position : Point
, velocity : Point
, dimensions : Point
}
type alias Hero =
Entity { isGrounded : Bool }
hero : Hero
hero =
{ position = Point 0 0
, velocity = Point 0 0
, dimensions = Point 10 10
, isGrounded = True
}
type alias Platform =
Entity {}
type alias Game =
{ hero : Hero
, platforms : List Platform
}
game : Game
game =
{ hero = hero
, platforms = []
}Render.elm module Platformer.Render where
import Platformer.Model (Game, Hero, Platform)
import Graphics.Collage (..)
import Graphics.Element (..)
import Color (..)
import List (..)
renderHero : Hero -> Form
renderHero hero =
move (hero.position.x, hero.position.y) <|
filled green <|
rect hero.dimensions.x hero.dimensions.y
renderPlatform : Platform -> Form
renderPlatform platform =
move (platform.position.x, platform.position.y) <|
filled blue <|
rect platform.dimensions.x platform.dimensions.y
render : Game -> Element
render game =
collage 400 400
((::) (renderHero game.hero)
(map renderPlatform game.platforms))
Platformer.elm import Platformer.Model (..)
import Platformer.Render (..)
main = render game |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Nope, I haven't gotten there, but I feel like I'm almost there. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
AHA!
import Graphics.Collage (filled, square, Form, collage)
import Graphics.Element (Element)
import Array (..)
import Color (green)
renderBox : (Float, Float) -> Form
renderBox (x,y) =
filled green <|
square 10
scene : Element
scene =
collage 400 400
(toList
(map renderBox empty))
main : Element
main = sceneThere seems to be an issue with mapping renderBox on empty
|
AHA! import Graphics.Collage (filled, square, Form, collage)
import Graphics.Element (Element)
import Array (..)
import Color (green)
renderBox : (Float, Float) -> Form
renderBox (x,y) =
filled green <|
square 10
scene : Element
scene =
collage 400 400
(toList
(map renderBox empty))
main : Element
main = sceneThere seems to be an issue with mapping renderBox on empty |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
Could it be related to this:
When I asText an empty list
import Text (asText)
main =
asText []I get this:
which is expected.
But if I toList an empty array and asText it
import Text (asText)
import Array (..)
main =
asText
(toList
(map (\x -> x * x) empty))I get this:
which is cryptic. I'd expect to just get the empty list with nothing inside.
In all those cases I was mapping a function over an empty array that was getting converted back to a list. Maybe that could be the problem?
|
Could it be related to this: When I import Text (asText)
main =
asText []I get this: which is expected. But if I import Text (asText)
import Array (..)
main =
asText
(toList
(map (\x -> x * x) empty))I get this: which is cryptic. I'd expect to just get the empty list with nothing inside. In all those cases I was mapping a function over an empty array that was getting converted back to a list. Maybe that could be the problem? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Feb 11, 2015
Member
Quite sketchy. I am not very familiar with the Array implementation, so I would not be terribly surprised if there was some bug there.
|
Quite sketchy. I am not very familiar with the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
Yeah it is.
I think I've found it, the bug is with the Array.map function.
If I convert an empty array to a list and ask for its length:
import Text (asText)
import Array (..)
import List
main =
asText
(List.length
(toList empty))
I get:
But, if I first map a function on an empty array and then call toList and ask for its length:
import Text (asText)
import Array (..)
import List
main =
asText
(List.length
(toList
(map (\x -> x * x) empty)))I get:
|
Yeah it is. I think I've found it, the bug is with the If I convert an empty array to a list and ask for its length: import Text (asText)
import Array (..)
import List
main =
asText
(List.length
(toList empty))
I get: But, if I first import Text (asText)
import Array (..)
import List
main =
asText
(List.length
(toList
(map (\x -> x * x) empty)))I get: |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
I'm not familiar with the Array implementation either, but at least now you know where to look :D
|
I'm not familiar with the Array implementation either, but at least now you know where to look :D |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
TheSeamau5
Feb 11, 2015
Contributor
So, I totally just found a quickfix to it and everything works! Yay!
The commit: fbea1ba
|
So, I totally just found a quickfix to it and everything works! Yay! The commit: fbea1ba |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Solved in: https://github.com/elm-lang/core/pull/171 |




TheSeamau5 commentedFeb 11, 2015
Seems like I got a runtime error.
Chrome is pointing at the
stepperHelpfunction inNative.Graphics.Collage. Somehow, something weird got through there and the compiler was silent.