mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
example/mapeditor: Draw map
This commit is contained in:
parent
8303fefdb9
commit
30aece193b
@ -35,7 +35,13 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
tileSet := mapeditor.NewTileSet(tileSetImg)
|
||||
editor = mapeditor.NewMainEditor(tileSet)
|
||||
|
||||
m := mapeditor.NewMap(20, 15)
|
||||
|
||||
editor, err = mapeditor.NewMainEditor(tileSet, m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func update(screen *ebiten.Image) error {
|
||||
@ -43,7 +49,7 @@ func update(screen *ebiten.Image) error {
|
||||
return err
|
||||
}
|
||||
|
||||
backgroundColor := color.RGBA{0x80, 0x80, 0x80, 0xff}
|
||||
backgroundColor := color.RGBA{0xc0, 0xc0, 0xc0, 0xff}
|
||||
screen.Fill(backgroundColor)
|
||||
return editor.Draw(screen)
|
||||
}
|
||||
|
@ -18,37 +18,62 @@ import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
const (
|
||||
tileSetX = 16
|
||||
tileSetY = 16
|
||||
tileSetWidth = TileSetXNum * TileWidth
|
||||
tileSetHeight = TileSetYNum * TileHeight
|
||||
mapViewX = 16 + TileWidth*TileSetXNum + 16
|
||||
mapViewY = 16
|
||||
mapViewWidth = 720
|
||||
mapViewHeight = 720
|
||||
)
|
||||
|
||||
type MainEditor struct {
|
||||
tileSet *TileSet
|
||||
tileSetX int
|
||||
tileSetY int
|
||||
selectedTile int
|
||||
tileSetView *TileSetView
|
||||
tileSetPanel *Panel
|
||||
mapView *MapView
|
||||
mapPanel *Panel
|
||||
mapCursorX int
|
||||
mapCursorY int
|
||||
}
|
||||
|
||||
func NewMainEditor(tileSet *TileSet) *MainEditor {
|
||||
return &MainEditor{
|
||||
tileSet: tileSet,
|
||||
tileSetX: 16,
|
||||
tileSetY: 16,
|
||||
func NewMainEditor(tileSet *TileSet, m *Map) (*MainEditor, error) {
|
||||
tileSetView := NewTileSetView(tileSet)
|
||||
tileSetPanel, err := NewPanel(tileSetView, tileSetX, tileSetY, tileSetWidth, tileSetHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapView := NewMapView(m)
|
||||
mapPanel, err := NewPanel(mapView, mapViewX, mapViewY, mapViewWidth, mapViewHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MainEditor{
|
||||
tileSetView: tileSetView,
|
||||
tileSetPanel: tileSetPanel,
|
||||
mapView: mapView,
|
||||
mapPanel: mapPanel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := m.tileSetView.Update(tileSetX, tileSetY); err != nil {
|
||||
return err
|
||||
}
|
||||
m.selectedTile = tile
|
||||
}
|
||||
tileSet := m.tileSetView.tileSet
|
||||
if err := m.mapView.Update(mapViewX, mapViewY, mapViewWidth, mapViewHeight, tileSet, m.tileSetView.selectedTile); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MainEditor) Draw(screen *ebiten.Image) error {
|
||||
return m.tileSet.Draw(screen, m.selectedTile, m.tileSetX, m.tileSetY)
|
||||
if err := m.tileSetPanel.Draw(screen); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := m.mapPanel.Draw(screen); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
89
example/mapeditor/mapeditor/map.go
Normal file
89
example/mapeditor/mapeditor/map.go
Normal file
@ -0,0 +1,89 @@
|
||||
// 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"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type Map struct {
|
||||
width int
|
||||
height int
|
||||
tiles []int
|
||||
}
|
||||
|
||||
func NewMap(width, height int) *Map {
|
||||
return &Map{
|
||||
width: width,
|
||||
height: height,
|
||||
tiles: make([]int, width*height),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) 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, nil
|
||||
}
|
||||
|
||||
func (m *Map) SetTile(x, y int, tile int) {
|
||||
i := x + y*m.width
|
||||
m.tiles[i] = tile
|
||||
}
|
||||
|
||||
type TileRects struct {
|
||||
m *Map
|
||||
}
|
||||
|
||||
func (t *TileRects) Len() int {
|
||||
return t.m.width * t.m.height
|
||||
}
|
||||
|
||||
func (t *TileRects) Src(i int) (x0, y0, x1, y1 int) {
|
||||
tile := t.m.tiles[i]
|
||||
x := tile % TileSetXNum * TileLogicWidth
|
||||
y := tile / TileSetXNum * TileLogicHeight
|
||||
return x, y, x + TileLogicWidth, y + TileLogicHeight
|
||||
}
|
||||
|
||||
func (t *TileRects) Dst(i int) (x0, y0, x1, y1 int) {
|
||||
x := i % t.m.width * TileLogicWidth
|
||||
y := i / t.m.width * TileLogicHeight
|
||||
return x, y, x + TileLogicWidth, y + TileLogicHeight
|
||||
}
|
||||
|
||||
func (m *Map) Draw(i *ebiten.Image, tileSetImg *ebiten.Image, x, y int) error {
|
||||
i.Fill(color.RGBA{0x80, 0x80, 0x80, 0xff})
|
||||
|
||||
op := &ebiten.DrawImageOptions{
|
||||
ImageParts: &TilesBackgroundRects{m.width, m.height},
|
||||
}
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
if err := i.DrawImage(tilesBackground, op); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
op = &ebiten.DrawImageOptions{
|
||||
ImageParts: &TileRects{m},
|
||||
}
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
op.GeoM.Scale(2, 2)
|
||||
if err := i.DrawImage(tileSetImg, op); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
72
example/mapeditor/mapeditor/mapview.go
Normal file
72
example/mapeditor/mapeditor/mapview.go
Normal file
@ -0,0 +1,72 @@
|
||||
// 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"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type MapView struct {
|
||||
m *Map
|
||||
tileSet *TileSet
|
||||
cursorX int
|
||||
cursorY int
|
||||
}
|
||||
|
||||
func NewMapView(m *Map) *MapView {
|
||||
return &MapView{
|
||||
m: m,
|
||||
cursorX: -1,
|
||||
cursorY: -1,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MapView) Update(ox, oy, width, height int, tileSet *TileSet, selectedTile int) error {
|
||||
m.tileSet = tileSet
|
||||
|
||||
x, y := ebiten.CursorPosition()
|
||||
x -= ox
|
||||
y -= oy
|
||||
if x < 0 || y < 0 || width <= x || height <= y {
|
||||
return nil
|
||||
}
|
||||
if m.m.width*TileWidth <= x || m.m.height*TileHeight <= y {
|
||||
return nil
|
||||
}
|
||||
m.cursorX = x / TileWidth
|
||||
m.cursorY = y / TileHeight
|
||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||
m.m.SetTile(m.cursorX, m.cursorY, selectedTile)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MapView) Draw(i *ebiten.Image, x, y, width, height int) error {
|
||||
if err := m.m.Draw(i, m.tileSet.image, x, y); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if m.cursorX == -1 || m.cursorY == -1 {
|
||||
return nil
|
||||
}
|
||||
sx := x + m.cursorX*TileWidth
|
||||
sy := y + m.cursorY*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
|
||||
}
|
59
example/mapeditor/mapeditor/panel.go
Normal file
59
example/mapeditor/mapeditor/panel.go
Normal file
@ -0,0 +1,59 @@
|
||||
// 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 drawer interface {
|
||||
Draw(target *ebiten.Image, x, y, width, height int) error
|
||||
}
|
||||
|
||||
type Panel struct {
|
||||
drawer drawer
|
||||
panelX int
|
||||
panelY int
|
||||
regionX int
|
||||
regionY int
|
||||
width int
|
||||
height int
|
||||
offscreen *ebiten.Image
|
||||
}
|
||||
|
||||
func NewPanel(drawer drawer, x, y, width, height int) (*Panel, error) {
|
||||
offscreen, err := ebiten.NewImage(width, height, ebiten.FilterNearest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Panel{
|
||||
drawer: drawer,
|
||||
panelX: x,
|
||||
panelY: y,
|
||||
width: width,
|
||||
height: height,
|
||||
offscreen: offscreen,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Panel) Draw(target *ebiten.Image) error {
|
||||
if err := p.drawer.Draw(p.offscreen, p.regionX, p.regionY, p.width, p.height); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(p.panelX), float64(p.panelY))
|
||||
return target.DrawImage(p.offscreen, op)
|
||||
}
|
@ -21,6 +21,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TileLogicWidth = 16
|
||||
TileLogicHeight = 16
|
||||
TileWidth = 32
|
||||
TileHeight = 32
|
||||
TileSetXNum = 8
|
||||
@ -82,7 +84,7 @@ func (t *TileSet) TileAt(x, y int) (int, error) {
|
||||
return x/TileWidth + y/TileHeight*TileSetXNum, nil
|
||||
}
|
||||
|
||||
func (t *TileSet) Draw(i *ebiten.Image, s int, x, y int) error {
|
||||
func (t *TileSet) Draw(i *ebiten.Image, x, y, width, height int) error {
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
op.ImageParts = &TilesBackgroundRects{8, 16}
|
||||
@ -97,11 +99,11 @@ func (t *TileSet) Draw(i *ebiten.Image, s int, x, y int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sx := x + s%TileSetXNum*TileWidth
|
||||
/*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)
|
||||
i.DrawRect(sx+2, sy+2, TileWidth-4, TileHeight-4, color.Black)*/
|
||||
|
||||
return nil
|
||||
}
|
||||
|
60
example/mapeditor/mapeditor/tilesetview.go
Normal file
60
example/mapeditor/mapeditor/tilesetview.go
Normal file
@ -0,0 +1,60 @@
|
||||
// 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"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type TileSetView struct {
|
||||
tileSet *TileSet
|
||||
selectedTile int
|
||||
}
|
||||
|
||||
func NewTileSetView(tileSet *TileSet) *TileSetView {
|
||||
return &TileSetView{
|
||||
tileSet: tileSet,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TileSetView) Update(ox, oy int) error {
|
||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||
x, y := ebiten.CursorPosition()
|
||||
x -= ox
|
||||
y -= oy
|
||||
if 0 <= x && 0 <= y && x < TileWidth*TileSetXNum && y < TileHeight*TileSetYNum {
|
||||
tile, err := t.tileSet.TileAt(x, y)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.selectedTile = tile
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TileSetView) Draw(i *ebiten.Image, x, y, width, height int) error {
|
||||
t.tileSet.Draw(i, x, y, width, height)
|
||||
|
||||
s := t.selectedTile
|
||||
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
|
||||
}
|
Loading…
Reference in New Issue
Block a user