diff --git a/ebiten.go b/ebiten.go index 5fb7720fa..ce2bffa23 100644 --- a/ebiten.go +++ b/ebiten.go @@ -29,14 +29,14 @@ const ( ) type Game interface { - ScreenWidth() int - ScreenHeight() int Init(tf graphics.TextureFactory) Update(context GameContext) Draw(context graphics.Context) } type GameContext interface { + ScreenWidth() int + ScreenHeight() int InputState() InputState Terminate() } diff --git a/example/game/blank/blank.go b/example/game/blank/blank.go index 635c5897c..035a43528 100644 --- a/example/game/blank/blank.go +++ b/example/game/blank/blank.go @@ -32,14 +32,6 @@ func New() *Blank { return &Blank{} } -func (game *Blank) ScreenWidth() int { - return 256 -} - -func (game *Blank) ScreenHeight() int { - return 240 -} - func (game *Blank) Init(tf graphics.TextureFactory) { } diff --git a/example/game/input/input.go b/example/game/input/input.go index 676536925..0d3e8f245 100644 --- a/example/game/input/input.go +++ b/example/game/input/input.go @@ -39,14 +39,6 @@ func New() *Input { return &Input{} } -func (game *Input) ScreenWidth() int { - return 256 -} - -func (game *Input) ScreenHeight() int { - return 240 -} - func (game *Input) Init(tf graphics.TextureFactory) { file, err := os.Open("images/text.png") if err != nil { diff --git a/example/game/monochrome/monochrome.go b/example/game/monochrome/monochrome.go index 8545e1bc0..4d6d75965 100644 --- a/example/game/monochrome/monochrome.go +++ b/example/game/monochrome/monochrome.go @@ -31,26 +31,20 @@ import ( ) type Monochrome struct { - ebitenTexture graphics.Texture - ch chan bool - colorMatrix matrix.Color + ebitenTexture graphics.Texture + ch chan bool + colorMatrix matrix.Color + geometryMatrix matrix.Geometry } func New() *Monochrome { return &Monochrome{ - ch: make(chan bool), - colorMatrix: matrix.IdentityColor(), + ch: make(chan bool), + colorMatrix: matrix.IdentityColor(), + geometryMatrix: matrix.IdentityGeometry(), } } -func (game *Monochrome) ScreenWidth() int { - return 256 -} - -func (game *Monochrome) ScreenHeight() int { - return 240 -} - func (game *Monochrome) Init(tf graphics.TextureFactory) { file, err := os.Open("images/ebiten.png") if err != nil { @@ -114,15 +108,16 @@ func (game *Monochrome) update() { func (game *Monochrome) Update(context ebiten.GameContext) { game.ch <- true <-game.ch + + game.geometryMatrix = matrix.IdentityGeometry() + tx := context.ScreenWidth()/2 - game.ebitenTexture.Width()/2 + ty := context.ScreenHeight()/2 - game.ebitenTexture.Height()/2 + game.geometryMatrix.Translate(float64(tx), float64(ty)) } func (game *Monochrome) Draw(g graphics.Context) { g.Fill(&color.RGBA{R: 128, G: 128, B: 255, A: 255}) - geometryMatrix := matrix.IdentityGeometry() - tx := game.ScreenWidth()/2 - game.ebitenTexture.Width()/2 - ty := game.ScreenHeight()/2 - game.ebitenTexture.Height()/2 - geometryMatrix.Translate(float64(tx), float64(ty)) g.DrawTexture(game.ebitenTexture.ID(), - geometryMatrix, game.colorMatrix) + game.geometryMatrix, game.colorMatrix) } diff --git a/example/game/rects/rects.go b/example/game/rects/rects.go index 1d5625d96..3b574a3e7 100644 --- a/example/game/rects/rects.go +++ b/example/game/rects/rects.go @@ -31,44 +31,38 @@ import ( type Rects struct { rectsTexture graphics.Texture + rect *graphics.Rect + rectColor *color.RGBA } func New() *Rects { - return &Rects{} -} - -func (game *Rects) ScreenWidth() int { - return 256 -} - -func (game *Rects) ScreenHeight() int { - return 240 + return &Rects{ + rect: &graphics.Rect{}, + rectColor: &color.RGBA{}, + } } func (game *Rects) Init(tf graphics.TextureFactory) { - game.rectsTexture = tf.NewTexture(game.ScreenWidth(), game.ScreenHeight()) + // TODO: fix + game.rectsTexture = tf.NewTexture(256, 240) } func (game *Rects) Update(context ebiten.GameContext) { + game.rect.X = rand.Intn(context.ScreenWidth()) + game.rect.Y = rand.Intn(context.ScreenHeight()) + game.rect.Width = rand.Intn(context.ScreenWidth() - game.rect.X) + game.rect.Height = rand.Intn(context.ScreenHeight() - game.rect.Y) + + game.rectColor.R = uint8(rand.Intn(256)) + game.rectColor.G = uint8(rand.Intn(256)) + game.rectColor.B = uint8(rand.Intn(256)) + game.rectColor.A = uint8(rand.Intn(256)) } func (game *Rects) Draw(g graphics.Context) { g.SetOffscreen(game.rectsTexture.ID()) - x := rand.Intn(game.ScreenWidth()) - y := rand.Intn(game.ScreenHeight()) - width := rand.Intn(game.ScreenWidth() - x) - height := rand.Intn(game.ScreenHeight() - y) - - red := uint8(rand.Intn(256)) - green := uint8(rand.Intn(256)) - blue := uint8(rand.Intn(256)) - alpha := uint8(rand.Intn(256)) - - g.DrawRect( - graphics.Rect{x, y, width, height}, - &color.RGBA{red, green, blue, alpha}, - ) + g.DrawRect(*game.rect, game.rectColor) g.SetOffscreen(g.Screen().ID()) g.DrawTexture(game.rectsTexture.ID(), diff --git a/example/game/rotating/rotating.go b/example/game/rotating/rotating.go index dd1b9ae50..917767ef0 100644 --- a/example/game/rotating/rotating.go +++ b/example/game/rotating/rotating.go @@ -32,22 +32,15 @@ import ( ) type Rotating struct { - ebitenTexture graphics.Texture - x int + ebitenTexture graphics.Texture + x int + geometryMatrix matrix.Geometry } func New() *Rotating { return &Rotating{} } -func (game *Rotating) ScreenWidth() int { - return 256 -} - -func (game *Rotating) ScreenHeight() int { - return 240 -} - func (game *Rotating) Init(tf graphics.TextureFactory) { file, err := os.Open("images/ebiten.png") if err != nil { @@ -66,21 +59,20 @@ func (game *Rotating) Init(tf graphics.TextureFactory) { func (game *Rotating) Update(context ebiten.GameContext) { game.x++ + + game.geometryMatrix = matrix.IdentityGeometry() + tx, ty := float64(game.ebitenTexture.Width()), float64(game.ebitenTexture.Height()) + game.geometryMatrix.Translate(-tx/2, -ty/2) + game.geometryMatrix.Rotate(float64(game.x) * 2 * math.Pi / float64(ebiten.FPS*10)) + game.geometryMatrix.Translate(tx/2, ty/2) + centerX := float64(context.ScreenWidth()) / 2 + centerY := float64(context.ScreenHeight()) / 2 + game.geometryMatrix.Translate(centerX-tx/2, centerY-ty/2) } func (game *Rotating) Draw(g graphics.Context) { g.Fill(&color.RGBA{R: 128, G: 128, B: 255, A: 255}) - - geometryMatrix := matrix.IdentityGeometry() - tx, ty := float64(game.ebitenTexture.Width()), float64(game.ebitenTexture.Height()) - geometryMatrix.Translate(-tx/2, -ty/2) - geometryMatrix.Rotate(float64(game.x) * 2 * math.Pi / float64(ebiten.FPS*10)) - geometryMatrix.Translate(tx/2, ty/2) - centerX := float64(game.ScreenWidth()) / 2 - centerY := float64(game.ScreenHeight()) / 2 - geometryMatrix.Translate(centerX-tx/2, centerY-ty/2) - g.DrawTexture(game.ebitenTexture.ID(), - geometryMatrix, + game.geometryMatrix, matrix.IdentityColor()) } diff --git a/example/game/sprites/sprites.go b/example/game/sprites/sprites.go index 35e2c5c76..2dcdc3fa3 100644 --- a/example/game/sprites/sprites.go +++ b/example/game/sprites/sprites.go @@ -88,14 +88,6 @@ func New() *Sprites { return &Sprites{} } -func (game *Sprites) ScreenWidth() int { - return 256 -} - -func (game *Sprites) ScreenHeight() int { - return 240 -} - func (game *Sprites) Init(tf graphics.TextureFactory) { file, err := os.Open("images/ebiten.png") if err != nil { @@ -112,9 +104,10 @@ func (game *Sprites) Init(tf graphics.TextureFactory) { } game.sprites = []*Sprite{} for i := 0; i < 100; i++ { + // TODO: fix sprite := newSprite( - game.ScreenWidth(), - game.ScreenHeight(), + 256, + 240, game.ebitenTexture.Width(), game.ebitenTexture.Height()) game.sprites = append(game.sprites, sprite) diff --git a/example/game/terminate/terminate.go b/example/game/terminate/terminate.go index 4773afd87..29371bb9a 100644 --- a/example/game/terminate/terminate.go +++ b/example/game/terminate/terminate.go @@ -33,14 +33,6 @@ func New() *Terminate { return &Terminate{60} } -func (game *Terminate) ScreenWidth() int { - return 256 -} - -func (game *Terminate) ScreenHeight() int { - return 240 -} - func (game *Terminate) Init(tf graphics.TextureFactory) { } diff --git a/example/main.go b/example/main.go index bd039e61d..f145cc047 100644 --- a/example/main.go +++ b/example/main.go @@ -63,5 +63,5 @@ func main() { } const screenScale = 2 - glut.Run(game, screenScale, "Ebiten Demo") + glut.Run(game, 256, 240, screenScale, "Ebiten Demo") } diff --git a/graphics/opengl/context.go b/graphics/opengl/context.go index ab4e86f9c..20558c286 100644 --- a/graphics/opengl/context.go +++ b/graphics/opengl/context.go @@ -42,12 +42,9 @@ type Context struct { screenScale int textures map[graphics.TextureID]*Texture currentOffscreen *Texture - projectionMatrix [16]float32 - currentShaderProgram C.GLuint mainFramebufferTexture *Texture } -// This method should be called on the UI thread. func newContext(screenWidth, screenHeight, screenScale int) *Context { context := &Context{ screenWidth: screenWidth, @@ -126,7 +123,6 @@ func (context *Context) DrawRect(rect graphics.Rect, clr color.Color) { } C.glUseProgram(0) - context.currentShaderProgram = 0 C.glDisable(C.GL_TEXTURE_2D) C.glEnableClientState(C.GL_VERTEX_ARRAY) C.glEnableClientState(C.GL_COLOR_ARRAY) @@ -161,11 +157,11 @@ func (context *Context) DrawTextureParts( panic("invalid texture ID") } - context.setShaderProgram(geometryMatrix, colorMatrix) + shaderProgram := context.setShaderProgram(geometryMatrix, colorMatrix) C.glBindTexture(C.GL_TEXTURE_2D, texture.id) - vertexAttrLocation := getAttributeLocation(context.currentShaderProgram, "vertex") - textureAttrLocation := getAttributeLocation(context.currentShaderProgram, "texture") + vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex") + textureAttrLocation := getAttributeLocation(shaderProgram, "texture") C.glEnableClientState(C.GL_VERTEX_ARRAY) C.glEnableClientState(C.GL_TEXTURE_COORD_ARRAY) @@ -220,10 +216,11 @@ func (context *Context) SetOffscreen(textureID graphics.TextureID) { texture.framebuffer = createFramebuffer(texture.id) } context.setOffscreen(texture) - context.currentOffscreen = texture } func (context *Context) setOffscreen(texture *Texture) { + context.currentOffscreen = texture + C.glFlush() C.glBindFramebuffer(C.GL_FRAMEBUFFER, texture.framebuffer) @@ -235,6 +232,18 @@ func (context *Context) setOffscreen(texture *Texture) { C.glViewport(0, 0, C.GLsizei(abs(texture.textureWidth)), C.GLsizei(abs(texture.textureHeight))) +} + +func (context *Context) resetOffscreen() { + context.setOffscreen(context.mainFramebufferTexture) +} + +func (context *Context) flush() { + C.glFlush() +} + +func (context *Context) projectionMatrix() [16]float32 { + texture := context.currentOffscreen var e11, e22, e41, e42 float32 if texture != context.mainFramebufferTexture { @@ -250,7 +259,7 @@ func (context *Context) setOffscreen(texture *Texture) { e42 = -1 + height/float32(texture.textureHeight)*2 } - context.projectionMatrix = [...]float32{ + return [...]float32{ e11, 0, 0, 0, 0, e22, 0, 0, 0, 0, 1, 0, @@ -258,20 +267,8 @@ func (context *Context) setOffscreen(texture *Texture) { } } -func (context *Context) resetOffscreen() { - context.setOffscreen(context.mainFramebufferTexture) - context.currentOffscreen = context.mainFramebufferTexture -} - -// This method should be called on the UI thread. -func (context *Context) flush() { - C.glFlush() -} - -// This method should be called on the UI thread. func (context *Context) setShaderProgram( - geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { - program := C.GLuint(0) + geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program C.GLuint) { if colorMatrix.IsIdentity() { program = regularShaderProgram } else { @@ -279,11 +276,11 @@ func (context *Context) setShaderProgram( } // TODO: cache and skip? C.glUseProgram(program) - context.currentShaderProgram = program + projectionMatrix := context.projectionMatrix() C.glUniformMatrix4fv(getUniformLocation(program, "projection_matrix"), 1, C.GL_FALSE, - (*C.GLfloat)(&context.projectionMatrix[0])) + (*C.GLfloat)(&projectionMatrix[0])) a := float32(geometryMatrix.Elements[0][0]) b := float32(geometryMatrix.Elements[0][1]) @@ -328,6 +325,8 @@ func (context *Context) setShaderProgram( } C.glUniform4fv(getUniformLocation(program, "color_matrix_translation"), 1, (*C.GLfloat)(&glColorMatrixTranslation[0])) + + return } func createFramebuffer(textureID C.GLuint) C.GLuint { diff --git a/ui/glut/glut.go b/ui/glut/glut.go index cd5b62631..075cd7972 100644 --- a/ui/glut/glut.go +++ b/ui/glut/glut.go @@ -135,10 +135,7 @@ func new(screenWidth, screenHeight, screenScale int, title string) *GlutUI { return ui } -func Run(game ebiten.Game, screenScale int, title string) { - screenWidth := game.ScreenWidth() - screenHeight := game.ScreenHeight() - +func Run(game ebiten.Game, screenWidth, screenHeight, screenScale int, title string) { ui := new(screenWidth, screenHeight, screenScale, title) currentUI = ui @@ -175,7 +172,9 @@ func Run(game ebiten.Game, screenScale int, title string) { int64(time.Second) / int64(ebiten.FPS)) tick := time.Tick(frameTime) gameContext := &GameContext{ - inputState: ebiten.InputState{-1, -1}, + screenWidth: screenWidth, + screenHeight: screenHeight, + inputState: ebiten.InputState{-1, -1}, } for { select { @@ -196,8 +195,18 @@ func Run(game ebiten.Game, screenScale int, title string) { } type GameContext struct { - inputState ebiten.InputState - terminated bool + screenWidth int + screenHeight int + inputState ebiten.InputState + terminated bool +} + +func (context *GameContext) ScreenWidth() int { + return context.screenWidth +} + +func (context *GameContext) ScreenHeight() int { + return context.screenHeight } func (context *GameContext) InputState() ebiten.InputState {