From 8303fefdb96fc405260701da06f1417e1f6d58c1 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 4 Feb 2015 03:15:53 +0900 Subject: [PATCH] Add example/mapeditor (WIP) --- example/mapeditor/main.go | 55 +++++++++++ example/mapeditor/mapeditor/maineditor.go | 54 +++++++++++ example/mapeditor/mapeditor/tileset.go | 107 ++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 example/mapeditor/main.go create mode 100644 example/mapeditor/mapeditor/maineditor.go create mode 100644 example/mapeditor/mapeditor/tileset.go diff --git a/example/mapeditor/main.go b/example/mapeditor/main.go new file mode 100644 index 000000000..2c88eda2b --- /dev/null +++ b/example/mapeditor/main.go @@ -0,0 +1,55 @@ +// Copyright 2015 Hajime Hoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/hajimehoshi/ebiten" + "github.com/hajimehoshi/ebiten/ebitenutil" + "github.com/hajimehoshi/ebiten/example/mapeditor/mapeditor" + "image/color" + "log" +) + +const ( + ScreenWidth = 1024 + ScreenHeight = 768 +) + +var editor *mapeditor.MainEditor + +func init() { + tileSetImg, _, err := ebitenutil.NewImageFromFile("images/platform/tileset.png", ebiten.FilterNearest) + if err != nil { + panic(err) + } + tileSet := mapeditor.NewTileSet(tileSetImg) + editor = mapeditor.NewMainEditor(tileSet) +} + +func update(screen *ebiten.Image) error { + if err := editor.Update(); err != nil { + return err + } + + backgroundColor := color.RGBA{0x80, 0x80, 0x80, 0xff} + screen.Fill(backgroundColor) + return editor.Draw(screen) +} + +func main() { + if err := ebiten.Run(update, ScreenWidth, ScreenHeight, 1, "Map Editor (Ebiten Demo)"); err != nil { + log.Fatal(err) + } +} diff --git a/example/mapeditor/mapeditor/maineditor.go b/example/mapeditor/mapeditor/maineditor.go new file mode 100644 index 000000000..a84189939 --- /dev/null +++ b/example/mapeditor/mapeditor/maineditor.go @@ -0,0 +1,54 @@ +// Copyright 2015 Hajime Hoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mapeditor + +import ( + "github.com/hajimehoshi/ebiten" +) + +type MainEditor struct { + tileSet *TileSet + tileSetX int + tileSetY int + selectedTile int +} + +func NewMainEditor(tileSet *TileSet) *MainEditor { + return &MainEditor{ + tileSet: tileSet, + tileSetX: 16, + tileSetY: 16, + } +} + +func (m *MainEditor) Update() error { + if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + x, y := ebiten.CursorPosition() + x -= m.tileSetX + y -= m.tileSetY + if 0 <= x && 0 <= y && x < TileWidth*TileSetXNum && y < TileHeight*TileSetYNum { + tile, err := m.tileSet.TileAt(x, y) + if err != nil { + return err + } + m.selectedTile = tile + } + } + return nil +} + +func (m *MainEditor) Draw(screen *ebiten.Image) error { + return m.tileSet.Draw(screen, m.selectedTile, m.tileSetX, m.tileSetY) +} diff --git a/example/mapeditor/mapeditor/tileset.go b/example/mapeditor/mapeditor/tileset.go new file mode 100644 index 000000000..07c9cfd3e --- /dev/null +++ b/example/mapeditor/mapeditor/tileset.go @@ -0,0 +1,107 @@ +// Copyright 2015 Hajime Hoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mapeditor + +import ( + "fmt" + "github.com/hajimehoshi/ebiten" + "image/color" +) + +const ( + TileWidth = 32 + TileHeight = 32 + TileSetXNum = 8 + TileSetYNum = 16 +) + +var tilesBackground *ebiten.Image + +const tilesBackgroundWidth = 32 +const tilesBackgroundHeight = 32 + +func init() { + var err error + tilesBackground, err = ebiten.NewImage(tilesBackgroundWidth, tilesBackgroundHeight, ebiten.FilterNearest) + if err != nil { + panic(err) + } + blue := color.RGBA{0x00, 0x00, 0x80, 0xff} + black := color.Black + tilesBackground.DrawFilledRect(0, 0, 16, 16, blue) + tilesBackground.DrawFilledRect(16, 0, 16, 16, black) + tilesBackground.DrawFilledRect(0, 16, 16, 16, black) + tilesBackground.DrawFilledRect(16, 16, 16, 16, blue) +} + +type TilesBackgroundRects struct { + xNum int + yNum int +} + +func (t *TilesBackgroundRects) Len() int { + return t.xNum * t.yNum +} + +func (t *TilesBackgroundRects) Src(i int) (x0, y0, x1, y1 int) { + return 0, 0, tilesBackgroundWidth, tilesBackgroundHeight +} + +func (t *TilesBackgroundRects) Dst(i int) (x0, y0, x1, y1 int) { + x := i % t.xNum * tilesBackgroundWidth + y := i / t.xNum * tilesBackgroundHeight + return x, y, x + tilesBackgroundWidth, y + tilesBackgroundHeight +} + +type TileSet struct { + image *ebiten.Image +} + +func NewTileSet(img *ebiten.Image) *TileSet { + return &TileSet{ + image: img, + } +} + +func (t *TileSet) TileAt(x, y int) (int, error) { + if x < 0 || y < 0 || TileWidth*TileSetXNum <= x || TileHeight*TileSetYNum <= y { + return 0, fmt.Errorf("out of range: (%d, %d)", x, y) + } + return x/TileWidth + y/TileHeight*TileSetXNum, nil +} + +func (t *TileSet) Draw(i *ebiten.Image, s int, x, y int) error { + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(float64(x), float64(y)) + op.ImageParts = &TilesBackgroundRects{8, 16} + if err := i.DrawImage(tilesBackground, op); err != nil { + return err + } + + op = &ebiten.DrawImageOptions{} + op.GeoM.Scale(2, 2) + op.GeoM.Translate(float64(x), float64(y)) + if err := i.DrawImage(t.image, op); err != nil { + return err + } + + sx := x + s%TileSetXNum*TileWidth + sy := y + s/TileSetXNum*TileHeight + i.DrawRect(sx, sy, TileWidth, TileHeight, color.Black) + i.DrawRect(sx+1, sy+1, TileWidth-2, TileHeight-2, color.White) + i.DrawRect(sx+2, sy+2, TileWidth-4, TileHeight-4, color.Black) + + return nil +}