ebiten/examples/blocks/blocks/piece.go

258 lines
4.9 KiB
Go
Raw Normal View History

// Copyright 2014 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.
2014-12-09 15:16:04 +01:00
2014-12-08 17:35:35 +01:00
package blocks
2013-12-18 19:21:25 +01:00
import (
"bytes"
2017-05-27 19:24:23 +02:00
"image"
_ "image/png"
2017-05-27 19:24:23 +02:00
2020-10-03 19:35:13 +02:00
"github.com/hajimehoshi/ebiten/v2"
rblocks "github.com/hajimehoshi/ebiten/v2/examples/resources/images/blocks"
2013-12-18 19:21:25 +01:00
)
var imageBlocks *ebiten.Image
2013-12-18 19:21:25 +01:00
func init() {
img, _, err := image.Decode(bytes.NewReader(rblocks.Blocks_png))
if err != nil {
panic(err)
}
imageBlocks = ebiten.NewImageFromImage(img)
2013-12-18 19:21:25 +01:00
}
2013-12-19 17:08:32 +01:00
type Angle int
const (
Angle0 Angle = iota
Angle90
Angle180
Angle270
)
func (a Angle) RotateRight() Angle {
if a == Angle270 {
return Angle0
}
return a + 1
}
2015-01-07 16:50:02 +01:00
func (a Angle) RotateLeft() Angle {
if a == Angle0 {
return Angle270
}
return a - 1
}
2013-12-18 19:21:25 +01:00
type BlockType int
const (
BlockTypeNone BlockType = iota
BlockType1
BlockType2
BlockType3
BlockType4
BlockType5
BlockType6
BlockType7
2014-12-29 05:36:29 +01:00
BlockTypeMax = BlockType7
2013-12-18 19:21:25 +01:00
)
type Piece struct {
blockType BlockType
blocks [][]bool
}
2018-01-22 07:12:17 +01:00
func transpose(bs [][]bool) [][]bool {
blocks := make([][]bool, len(bs))
for j, row := range bs {
2013-12-19 17:08:32 +01:00
blocks[j] = make([]bool, len(row))
}
// Tranpose the argument matrix.
2018-01-22 07:12:17 +01:00
for i, col := range bs {
2013-12-19 17:08:32 +01:00
for j, v := range col {
2018-01-22 07:12:17 +01:00
blocks[j][i] = v
2013-12-18 19:21:25 +01:00
}
}
return blocks
}
2018-01-22 07:12:17 +01:00
// Pieces is the set of all the possible pieces.
var Pieces map[BlockType]*Piece
func init() {
const (
f = false
t = true
)
Pieces = map[BlockType]*Piece{
BlockType1: {
blockType: BlockType1,
blocks: transpose([][]bool{
{f, f, f, f},
{t, t, t, t},
{f, f, f, f},
{f, f, f, f},
}),
},
BlockType2: {
blockType: BlockType2,
blocks: transpose([][]bool{
{t, f, f},
{t, t, t},
{f, f, f},
}),
},
BlockType3: {
blockType: BlockType3,
blocks: transpose([][]bool{
{f, t, f},
{t, t, t},
{f, f, f},
}),
},
BlockType4: {
blockType: BlockType4,
blocks: transpose([][]bool{
{f, f, t},
{t, t, t},
{f, f, f},
}),
},
BlockType5: {
blockType: BlockType5,
blocks: transpose([][]bool{
{t, t, f},
{f, t, t},
{f, f, f},
}),
},
BlockType6: {
blockType: BlockType6,
blocks: transpose([][]bool{
{f, t, t},
{t, t, f},
{f, f, f},
}),
},
BlockType7: {
blockType: BlockType7,
blocks: transpose([][]bool{
{t, t},
{t, t},
}),
},
}
2013-12-18 19:21:25 +01:00
}
2017-05-27 19:24:23 +02:00
const (
blockWidth = 10
blockHeight = 10
fieldBlockNumX = 10
fieldBlockNumY = 20
)
2015-01-03 15:20:17 +01:00
2018-01-22 07:12:17 +01:00
func drawBlock(r *ebiten.Image, block BlockType, x, y int, clr ebiten.ColorM) {
if block == BlockTypeNone {
return
}
2017-05-27 19:24:23 +02:00
op := &ebiten.DrawImageOptions{}
op.ColorM = clr
2018-01-22 07:12:17 +01:00
op.GeoM.Translate(float64(x), float64(y))
srcX := (int(block) - 1) * blockWidth
r.DrawImage(imageBlocks.SubImage(image.Rect(srcX, 0, srcX+blockWidth, blockHeight)).(*ebiten.Image), op)
2013-12-18 19:21:25 +01:00
}
2013-12-19 17:08:32 +01:00
func (p *Piece) InitialPosition() (int, int) {
size := len(p.blocks)
x := (fieldBlockNumX - size) / 2
y := 0
Loop:
for j := 0; j < size; j++ {
for i := 0; i < size; i++ {
if p.blocks[i][j] {
break Loop
}
}
y--
}
return x, y
}
2018-01-22 07:12:17 +01:00
// isBlocked returns a boolean value indicating whether
// there is a block at the position (x, y) of the piece with the given angle.
2013-12-19 17:08:32 +01:00
func (p *Piece) isBlocked(i, j int, angle Angle) bool {
size := len(p.blocks)
i2, j2 := i, j
switch angle {
case Angle0:
case Angle90:
i2 = j
2014-01-07 15:29:12 +01:00
j2 = size - 1 - i
2013-12-19 17:08:32 +01:00
case Angle180:
2014-01-07 15:29:12 +01:00
i2 = size - 1 - i
j2 = size - 1 - j
2013-12-19 17:08:32 +01:00
case Angle270:
2014-01-07 15:29:12 +01:00
i2 = size - 1 - j
2013-12-19 17:08:32 +01:00
j2 = i
}
return p.blocks[i2][j2]
}
2018-01-22 07:12:17 +01:00
// collides returns a boolean value indicating whether
// the piece at (x, y) with the given angle would collide with the field's blocks.
2013-12-19 17:08:32 +01:00
func (p *Piece) collides(field *Field, x, y int, angle Angle) bool {
size := len(p.blocks)
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
if field.IsBlocked(x+i, y+j) && p.isBlocked(i, j, angle) {
return true
}
}
}
return false
}
2013-12-26 16:37:36 +01:00
func (p *Piece) AbsorbInto(field *Field, x, y int, angle Angle) {
2013-12-19 19:21:10 +01:00
size := len(p.blocks)
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
if p.isBlocked(i, j, angle) {
2014-12-07 16:07:36 +01:00
field.setBlock(x+i, y+j, p.blockType)
2013-12-19 19:21:10 +01:00
}
}
}
}
func (p *Piece) DrawAtCenter(r *ebiten.Image, x, y, width, height int, angle Angle) {
2014-12-29 06:27:43 +01:00
x += (width - len(p.blocks[0])*blockWidth) / 2
y += (height - len(p.blocks)*blockHeight) / 2
p.Draw(r, x, y, angle)
2014-12-29 06:27:43 +01:00
}
func (p *Piece) Draw(r *ebiten.Image, x, y int, angle Angle) {
2014-12-06 14:56:57 +01:00
for i := range p.blocks {
2018-01-22 07:12:17 +01:00
for j := range p.blocks[i] {
2013-12-19 17:08:32 +01:00
if p.isBlocked(i, j, angle) {
2018-01-22 07:12:17 +01:00
drawBlock(r, p.blockType, i*blockWidth+x, j*blockHeight+y, ebiten.ColorM{})
2013-12-18 19:21:25 +01:00
}
}
}
2018-01-22 07:12:17 +01:00
2013-12-18 19:21:25 +01:00
}