Merge pull request #3 from genxium/backend_collision

Added backend collision handling.
This commit is contained in:
Wing 2022-10-15 21:56:23 +08:00 committed by GitHub
commit 0047259e9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 843 additions and 611 deletions

View File

@ -2,10 +2,10 @@ package api
import (
"bytes"
. "dnmshared"
"github.com/gin-gonic/gin"
"io"
"io/ioutil"
. "server/common"
)
func RequestLogger() gin.HandlerFunc {

View File

@ -16,6 +16,8 @@ import (
"server/models"
"server/storage"
"strconv"
. "dnmshared"
)
var Player = playerController{}

View File

@ -1,16 +1,15 @@
package common
import (
. "dnmshared"
"encoding/json"
"fmt"
"go.uber.org/zap"
"os"
"path/filepath"
"strings"
"go.uber.org/zap"
)
// 隐式导入
var Conf *config
const (
@ -72,11 +71,15 @@ func MustParseConfig() {
BotServer: new(botServerConf),
}
execPath, err := os.Executable()
ErrFatal(err)
if nil != err {
panic(err)
}
pwd, err := os.Getwd()
Logger.Debug("os.GetWd", zap.String("pwd", pwd))
ErrFatal(err)
if nil != err {
panic(err)
}
appRoot := pwd
confDir := filepath.Join(appRoot, "configs")
@ -129,22 +132,21 @@ func loadJSON(fp string, v interface{}) {
fp = filepath.Join(Conf.General.ConfDir, fp)
}
_, err := os.Stat(fp)
ErrFatal(err)
if nil != err {
panic(err)
}
fd, err := os.Open(fp)
ErrFatal(err)
if nil != err {
panic(err)
}
defer fd.Close()
Logger.Info("Opened json file successfully.", zap.String("fp", fp))
err = json.NewDecoder(fd).Decode(v)
ErrFatal(err)
Logger.Info("Loaded json file successfully.", zap.String("fp", fp))
}
// Please only use this auxiliary function before server is fully started up, but not afterwards (启动过程可以使用,运行时不准使用).
func ErrFatal(err error) {
if err != nil {
Logger.Fatal("ErrFatal", zap.NamedError("err", err))
if nil != err {
panic(err)
}
Logger.Info("Loaded json file successfully.", zap.String("fp", fp))
}
func isNotExist(p string) bool {

View File

@ -5,9 +5,10 @@ import (
"github.com/imdario/mergo"
"go.uber.org/zap"
. "dnmshared"
)
// 隐式导入
var Constants *constants
func MustParseConstants() {
@ -24,13 +25,11 @@ func MustParseConstants() {
if !isNotExist(fp) {
testConstants := new(constants)
loadJSON(fp, testConstants)
//Logger.Debug(spew.Sdump(Constants))
//Logger.Debug(spew.Sdump(testConstants))
err := mergo.Merge(testConstants, Constants)
ErrFatal(err)
if nil != err {
panic(err)
}
Constants = testConstants
//Logger.Debug("mergo.Merge", zap.Error(err))
//Logger.Debug(spew.Sdump(testConstants))
}
}
constantsPost()

View File

@ -3,6 +3,7 @@ package utils
import (
"bytes"
"crypto/sha1"
. "dnmshared"
"encoding/json"
"fmt"
"go.uber.org/zap"

View File

@ -11,7 +11,6 @@ var (
RE_CHINA_PHONE_NUM = regexp.MustCompile(`^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$`)
)
// 隐式导入
var ConstVals = &struct {
Player struct {
CaptchaExpire time.Duration

View File

@ -1,6 +1,7 @@
package env_tools
import (
. "dnmshared"
sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
@ -15,7 +16,9 @@ func LoadPreConf() {
Logger.Info(`Merging PreConfSQLite data into MySQL`,
zap.String("PreConfSQLitePath", Conf.General.PreConfSQLitePath))
db, err := sqlx.Connect("sqlite3", Conf.General.PreConfSQLitePath)
ErrFatal(err)
if nil != err {
panic(err)
}
defer db.Close()
loadPreConfToMysql(db)
@ -39,7 +42,9 @@ func loadPreConfToMysql(db *sqlx.DB) {
func loadSqlite(db *sqlx.DB, tbs []string) {
for _, v := range tbs {
result, err := storage.MySQLManagerIns.Exec("truncate " + v)
ErrFatal(err)
if nil != err {
panic(err)
}
Logger.Info("truncate", zap.Any("truncate "+v, result))
query, args, err := sq.Select("*").From(v).ToSql()
if err != nil {
@ -70,19 +75,25 @@ func createMysqlData(rows *sqlx.Rows, v string) {
func maybeCreateNewPlayerFromBotTable(db *sqlx.DB, tableName string) {
var ls []*dbBotPlayer
err := db.Select(&ls, "SELECT name, magic_phone_country_code, magic_phone_num, display_name FROM "+tableName)
ErrFatal(err)
if nil != err {
panic(err)
}
names := make([]string, len(ls), len(ls))
for i, v := range ls {
names[i] = v.Name
}
sql := "SELECT name FROM `player` WHERE name in (?)"
query, args, err := sqlx.In(sql, names)
ErrFatal(err)
if nil != err {
panic(err)
}
query = storage.MySQLManagerIns.Rebind(query)
// existNames := make([]string, len(ls), len(ls))
var existPlayers []*models.Player
err = storage.MySQLManagerIns.Select(&existPlayers, query, args...)
ErrFatal(err)
if nil != err {
panic(err)
}
for _, botPlayer := range ls {
var flag bool

View File

@ -1,6 +1,7 @@
package env_tools
import (
. "dnmshared"
. "server/common"
"server/common/utils"
"server/models"
@ -15,7 +16,9 @@ func MergeTestPlayerAccounts() {
fp := Conf.General.TestEnvSQLitePath
Logger.Info(`Initializing TestPlayerAccounts in runtime MySQLServer from SQLite file:`, zap.String("fp", fp))
db, err := sqlx.Connect("sqlite3", fp)
ErrFatal(err)
if nil != err {
panic(err)
}
defer db.Close()
maybeCreateNewPlayer(db, "test_player")
}
@ -29,31 +32,35 @@ type dbTestPlayer struct {
func maybeCreateNewPlayer(db *sqlx.DB, tableName string) {
var ls []*dbTestPlayer
err := db.Select(&ls, "SELECT name, magic_phone_country_code, magic_phone_num FROM "+tableName)
ErrFatal(err)
if nil != err {
panic(err)
}
names := make([]string, len(ls), len(ls))
for i, v := range ls {
names[i] = v.Name
}
sql := "SELECT name FROM `player` WHERE name in (?)"
query, args, err := sqlx.In(sql, names)
ErrFatal(err)
if nil != err {
panic(err)
}
query = storage.MySQLManagerIns.Rebind(query)
// existNames := make([]string, len(ls), len(ls))
var existPlayers []*models.Player
err = storage.MySQLManagerIns.Select(&existPlayers, query, args...)
ErrFatal(err)
if nil != err {
panic(err)
}
for _, testPlayer := range ls {
var flag bool
for _, v := range existPlayers {
if testPlayer.Name == v.Name {
// 已有数据,合并处理
flag = true
break
}
}
if !flag {
// 找不到,新增
Logger.Debug("create", zap.Any(tableName, testPlayer))
err := createNewPlayer(testPlayer)
if err != nil {

View File

@ -3,7 +3,6 @@ module server
go 1.19
require (
github.com/ByteArena/box2d v1.0.2
github.com/Masterminds/squirrel v0.0.0-20180815162352-8a7e65843414
github.com/davecgh/go-spew v1.1.1
github.com/gin-contrib/cors v0.0.0-20180514151808-6f0a820f94be
@ -21,6 +20,8 @@ require (
github.com/thoas/go-funk v0.0.0-20180716193722-1060394a7713
go.uber.org/zap v1.9.1
google.golang.org/protobuf v1.28.1
dnmshared v0.0.0
)
require (
@ -44,3 +45,7 @@ require (
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
gopkg.in/yaml.v2 v2.2.1 // indirect
)
replace (
dnmshared => ../dnmshared
)

View File

@ -10,8 +10,6 @@ import (
"server/api"
"server/api/v1"
. "server/common"
"server/common/utils"
"server/configs"
"server/env_tools"
"server/models"
"server/storage"
@ -19,6 +17,8 @@ import (
"syscall"
"time"
. "dnmshared"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/robfig/cron"
@ -30,8 +30,6 @@ func main() {
MustParseConstants()
storage.Init()
env_tools.LoadPreConf()
utils.InitWechat(configs.WechatConfigIns)
utils.InitWechatGame(configs.WechatGameConfigIns)
if Conf.General.ServerEnv == SERVER_ENV_TEST {
env_tools.MergeTestPlayerAccounts()
}

View File

@ -1,5 +1,9 @@
package models
import (
. "dnmshared"
)
type Barrier struct {
Boundary *Polygon2D
}

View File

@ -1,132 +0,0 @@
package models
import (
"fmt"
"github.com/ByteArena/box2d"
"math"
)
// Use type `float64` for json unmarshalling of numbers.
type Direction struct {
Dx int32 `json:"dx,omitempty"`
Dy int32 `json:"dy,omitempty"`
}
type Vec2D struct {
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
}
func CreateVec2DFromB2Vec2(b2V2 box2d.B2Vec2) *Vec2D {
return &Vec2D{
X: b2V2.X,
Y: b2V2.Y,
}
}
func (v2 *Vec2D) ToB2Vec2() box2d.B2Vec2 {
return box2d.MakeB2Vec2(v2.X, v2.Y)
}
type Polygon2D struct {
Anchor *Vec2D `json:"-"` // This "Polygon2D.Anchor" is used to be assigned to "B2BodyDef.Position", which in turn is used as the position of the FIRST POINT of the polygon.
Points []*Vec2D `json:"-"`
/*
When used to represent a "polyline directly drawn in a `Tmx file`", we can initialize both "Anchor" and "Points" simultaneously.
Yet when used to represent a "polyline drawn in a `Tsx file`", we have to first initialize "Points w.r.t. center of the tile-rectangle", and then "Anchor(initially nil) of the tile positioned in the `Tmx file`".
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for more information.
*/
/*
[WARNING] Used to cache "`TileWidth & TileHeight` of a Tsx file" only.
*/
TileWidth int
TileHeight int
/*
[WARNING] Used to cache "`Width & TileHeight` of an object in Tmx file" only.
*/
TmxObjectWidth float64
TmxObjectHeight float64
}
func MoveDynamicBody(body *box2d.B2Body, pToTargetPos *box2d.B2Vec2, inSeconds float64) {
if body.GetType() != box2d.B2BodyType.B2_dynamicBody {
return
}
body.SetTransform(*pToTargetPos, 0.0)
body.SetLinearVelocity(box2d.MakeB2Vec2(0.0, 0.0))
body.SetAngularVelocity(0.0)
}
func PrettyPrintFixture(fix *box2d.B2Fixture) {
fmt.Printf("\t\tfriction:\t%v\n", fix.M_friction)
fmt.Printf("\t\trestitution:\t%v\n", fix.M_restitution)
fmt.Printf("\t\tdensity:\t%v\n", fix.M_density)
fmt.Printf("\t\tisSensor:\t%v\n", fix.M_isSensor)
fmt.Printf("\t\tfilter.categoryBits:\t%d\n", fix.M_filter.CategoryBits)
fmt.Printf("\t\tfilter.maskBits:\t%d\n", fix.M_filter.MaskBits)
fmt.Printf("\t\tfilter.groupIndex:\t%d\n", fix.M_filter.GroupIndex)
switch fix.M_shape.GetType() {
case box2d.B2Shape_Type.E_circle:
{
s := fix.M_shape.(*box2d.B2CircleShape)
fmt.Printf("\t\tb2CircleShape shape: {\n")
fmt.Printf("\t\t\tradius:\t%v\n", s.M_radius)
fmt.Printf("\t\t\toffset:\t%v\n", s.M_p)
fmt.Printf("\t\t}\n")
}
break
case box2d.B2Shape_Type.E_polygon:
{
s := fix.M_shape.(*box2d.B2PolygonShape)
fmt.Printf("\t\tb2PolygonShape shape: {\n")
for i := 0; i < s.M_count; i++ {
fmt.Printf("\t\t\t%v\n", s.M_vertices[i])
}
fmt.Printf("\t\t}\n")
}
break
default:
break
}
}
func PrettyPrintBody(body *box2d.B2Body) {
bodyIndex := body.M_islandIndex
fmt.Printf("{\n")
fmt.Printf("\tHeapRAM addr:\t%p\n", body)
fmt.Printf("\ttype:\t%d\n", body.M_type)
fmt.Printf("\tposition:\t%v\n", body.GetPosition())
fmt.Printf("\tangle:\t%v\n", body.M_sweep.A)
fmt.Printf("\tlinearVelocity:\t%v\n", body.GetLinearVelocity())
fmt.Printf("\tangularVelocity:\t%v\n", body.GetAngularVelocity())
fmt.Printf("\tlinearDamping:\t%v\n", body.M_linearDamping)
fmt.Printf("\tangularDamping:\t%v\n", body.M_angularDamping)
fmt.Printf("\tallowSleep:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_autoSleepFlag)
fmt.Printf("\tawake:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_awakeFlag)
fmt.Printf("\tfixedRotation:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_fixedRotationFlag)
fmt.Printf("\tbullet:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_bulletFlag)
fmt.Printf("\tactive:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_activeFlag)
fmt.Printf("\tgravityScale:\t%v\n", body.M_gravityScale)
fmt.Printf("\tislandIndex:\t%v\n", bodyIndex)
fmt.Printf("\tfixtures: {\n")
for f := body.M_fixtureList; f != nil; f = f.M_next {
PrettyPrintFixture(f)
}
fmt.Printf("\t}\n")
fmt.Printf("}\n")
}
func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 {
dx := pt1.X - pt2.X
dy := pt1.Y - pt2.Y
return math.Sqrt(dx*dx + dy*dy)
}

View File

@ -1,6 +1,7 @@
package models
import (
. "dnmshared"
pb "server/pb_output"
)

View File

@ -2,6 +2,7 @@ package models
import (
"database/sql"
. "dnmshared"
"fmt"
sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"

View File

@ -2,7 +2,7 @@ package models
import (
"database/sql"
. "server/common"
. "dnmshared"
"server/storage"
sq "github.com/Masterminds/squirrel"

View File

@ -2,6 +2,7 @@ package models
import (
"database/sql"
. "dnmshared"
"errors"
. "server/common"
"server/common/utils"

View File

@ -1,17 +1,14 @@
package models
import (
"encoding/xml"
. "dnmshared"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"github.com/solarlune/resolv"
"go.uber.org/zap"
"io/ioutil"
"math"
"math/rand"
"os"
"path/filepath"
. "server/common"
"server/common/utils"
pb "server/pb_output"
@ -19,6 +16,11 @@ import (
"sync"
"sync/atomic"
"time"
"encoding/xml"
"io/ioutil"
"os"
"path/filepath"
)
const (
@ -261,10 +263,12 @@ func (pR *Room) ChooseStage() error {
* -- YFLu, 2019-09-04
*/
pwd, err := os.Getwd()
ErrFatal(err)
if nil != err {
panic(err)
}
rand.Seed(time.Now().Unix())
stageNameList := []string{ /*"pacman" ,*/ "richsoil"}
stageNameList := []string{ /*"simple" ,*/ "richsoil"}
chosenStageIndex := rand.Int() % len(stageNameList) // Hardcoded temporarily. -- YFLu
pR.StageName = stageNameList[chosenStageIndex]
@ -324,7 +328,8 @@ func (pR *Room) ChooseStage() error {
barrierPolygon2DList := *(toRetStrToPolygon2DListMap["Barrier"])
var barrierLocalIdInBattle int32 = 0
for _, polygon2D := range barrierPolygon2DList {
for _, polygon2DUnaligned := range barrierPolygon2DList {
polygon2D := AlignPolygon2DToBoundingBox(polygon2DUnaligned)
/*
// For debug-printing only.
Logger.Info("ChooseStage printing polygon2D for barrierPolygon2DList", zap.Any("barrierLocalIdInBattle", barrierLocalIdInBattle), zap.Any("polygon2D.Anchor", polygon2D.Anchor), zap.Any("polygon2D.Points", polygon2D.Points))
@ -435,13 +440,13 @@ func (pR *Room) StartBattle() {
elapsedNanosSinceLastFrameIdTriggered := stCalculation - pR.LastRenderFrameIdTriggeredAt
if elapsedNanosSinceLastFrameIdTriggered < pR.RollbackEstimatedDtNanos {
Logger.Debug(fmt.Sprintf("Avoiding too fast frame@roomId=%v, renderFrameId=%v: elapsedNanosSinceLastFrameIdTriggered=%v", pR.Id, pR.RenderFrameId, elapsedNanosSinceLastFrameIdTriggered))
continue
continue
}
if pR.RenderFrameId > pR.BattleDurationFrames {
Logger.Info(fmt.Sprintf("The `battleMainLoop` for roomId=%v is stopped@renderFrameId=%v, with battleDurationFrames=%v:\n%v", pR.Id, pR.RenderFrameId, pR.BattleDurationFrames, pR.InputsBufferString(true)))
pR.StopBattleForSettlement()
return
return
}
if swapped := atomic.CompareAndSwapInt32(&pR.State, RoomBattleStateIns.IN_BATTLE, RoomBattleStateIns.IN_BATTLE); !swapped {
@ -623,9 +628,9 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
inputFrameId := inputFrameDownsync.InputFrameId
if -1 == pR.LastAllConfirmedInputFrameIdWithChange || false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) {
if -1 == playerId {
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
Logger.Debug(fmt.Sprintf("Key inputFrame change: roomId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
} else {
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
Logger.Debug(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
}
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), inputFrameId)
}
@ -637,7 +642,7 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
if -1 == playerId {
Logger.Debug(fmt.Sprintf("inputFrame lifecycle#2[forced-allconfirmed]: roomId=%v, InputsBuffer=%v", pR.Id, pR.InputsBufferString(false)))
} else {
Logger.Info(fmt.Sprintf("inputFrame lifecycle#2[allconfirmed]: roomId=%v, playerId=%v, InputsBuffer=%v", pR.Id, playerId, pR.InputsBufferString(false)))
Logger.Debug(fmt.Sprintf("inputFrame lifecycle#2[allconfirmed]: roomId=%v, playerId=%v, InputsBuffer=%v", pR.Id, playerId, pR.InputsBufferString(false)))
}
}
@ -789,8 +794,8 @@ func (pR *Room) OnDismissed() {
pR.NstDelayFrames = 8
pR.InputScaleFrames = uint32(2)
pR.ServerFps = 60
pR.RollbackEstimatedDt = 0.016667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDt = 0.016667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME
pR.BattleDurationFrames = 30 * pR.ServerFps
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
@ -1142,17 +1147,23 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
encodedInput := inputList[joinIndex-1]
decodedInput := DIRECTION_DECODER[encodedInput]
decodedInputSpeedFactor := DIRECTION_DECODER_INVERSE_LENGTH[encodedInput]
if 0.0 == decodedInputSpeedFactor {
continue
}
baseChange := player.Speed * pR.RollbackEstimatedDt * decodedInputSpeedFactor
dx := baseChange * float64(decodedInput[0])
dy := baseChange * float64(decodedInput[1])
// The collision lib seems very slow at worst cases, omitting for now
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
if collision := playerCollider.Check(dx, dy, "Barrier"); collision != nil {
changeWithCollision := collision.ContactWithObject(collision.Objects[0])
dx = changeWithCollision.X()
dy = changeWithCollision.Y()
Logger.Info(fmt.Sprintf("Collided: roomId=%v, playerId=%v, orig dx=%v, orig dy=%v, proposed new dx =%v, proposed new dy=%v", pR.Id, player.Id, dx, dy, changeWithCollision.X(), changeWithCollision.Y()))
// FIXME: Use a mechanism equivalent to that of the frontend!
// dx = changeWithCollision.X()
// dy = changeWithCollision.Y()
dx = 0
dy = 0
}
playerCollider.X += dx
playerCollider.Y += dy
@ -1169,7 +1180,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
newRenderFrame := pb.RoomDownsyncFrame{
Id: collisionSysRenderFrameId + 1,
Players: toPbPlayers(pR.Players),
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*pR.RollbackEstimatedDtNanos),
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*pR.RollbackEstimatedDtNanos),
}
pR.RenderFrameBuffer.Put(&newRenderFrame)
pR.CurDynamicsRenderFrameId++
@ -1181,11 +1192,19 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
}
func (pR *Room) refreshColliders() {
playerColliderRadius := float64(12) // hardcoded
// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups"
space := resolv.NewSpace(int(pR.StageDiscreteW), int(pR.StageDiscreteH), int(pR.StageTileW), int(pR.StageTileH)) // allocate a new collision space everytime after a battle is settled
spaceW := pR.StageDiscreteW * pR.StageTileW
spaceH := pR.StageDiscreteH * pR.StageTileH
spaceOffsetX := float64(spaceW) * 0.5
spaceOffsetY := float64(spaceH) * 0.5
minStep := int(3) // the approx minimum distance a player can move per frame
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
for _, player := range pR.Players {
playerCollider := resolv.NewObject(player.X, player.Y, 12, 12) // Radius=12 is hardcoded
playerColliderShape := resolv.NewCircle(player.X, player.Y, 12)
playerCollider := resolv.NewObject(player.X+spaceOffsetX, player.Y+spaceOffsetY, playerColliderRadius*2, playerColliderRadius*2)
playerColliderShape := resolv.NewCircle(0, 0, playerColliderRadius*2)
playerCollider.SetShape(playerColliderShape)
space.Add(playerCollider)
// Keep track of the collider in "pR.CollisionSysMap"
@ -1196,8 +1215,10 @@ func (pR *Room) refreshColliders() {
}
for _, barrier := range pR.Barriers {
var w float64 = 0
var h float64 = 0
for i, pi := range barrier.Boundary.Points {
for j, pj := range barrier.Boundary.Points {
if i == j {
@ -1214,13 +1235,12 @@ func (pR *Room) refreshColliders() {
barrierColliderShape := resolv.NewConvexPolygon()
for _, p := range barrier.Boundary.Points {
barrierColliderShape.AddPoints(p.X+barrier.Boundary.Anchor.X, p.Y+barrier.Boundary.Anchor.Y)
barrierColliderShape.AddPoints(p.X, p.Y)
}
barrierCollider := resolv.NewObject(barrier.Boundary.Anchor.X, barrier.Boundary.Anchor.Y, w, h, "Barrier")
barrierCollider := resolv.NewObject(barrier.Boundary.Anchor.X+spaceOffsetX, barrier.Boundary.Anchor.Y+spaceOffsetY, w, h, "Barrier")
barrierCollider.SetShape(barrierColliderShape)
space.Add(barrierCollider)
pR.printBarrier(barrierCollider)
}
}

View File

@ -2,9 +2,9 @@ package models
import (
"container/heap"
. "dnmshared"
"fmt"
"go.uber.org/zap"
. "server/common"
"sync"
)

View File

@ -6,6 +6,8 @@ import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"go.uber.org/zap"
. "dnmshared"
)
var (
@ -15,8 +17,12 @@ var (
func initMySQL() {
var err error
MySQLManagerIns, err = sqlx.Connect("mysql", Conf.MySQL.DSN+"?charset=utf8mb4")
ErrFatal(err)
if nil != err {
panic(err)
}
err = MySQLManagerIns.Ping()
ErrFatal(err)
if nil != err {
panic(err)
}
Logger.Info("MySQLManagerIns", zap.Any("mysql", MySQLManagerIns))
}

View File

@ -7,6 +7,8 @@ import (
"github.com/go-redis/redis"
_ "github.com/go-sql-driver/mysql"
"go.uber.org/zap"
. "dnmshared"
)
var (
@ -20,6 +22,8 @@ func initRedis() {
DB: Conf.Redis.Dbname, // use default DB
})
pong, err := RedisManagerIns.Ping().Result()
ErrFatal(err)
if nil != err {
panic(err)
}
Logger.Info("Redis", zap.String("ping", pong))
}

View File

@ -17,7 +17,9 @@ func loadTMX(fp string, pTmxMapIns *models.TmxMap) {
}
byteArr, err := ioutil.ReadFile(fp)
ErrFatal(err)
if nil != err {
panic(err)
}
models.DeserializeToTmxMapIns(byteArr, pTmxMapIns)
for _, info := range pTmxMapIns.TreasuresInfo {
fmt.Printf("treasuresInfo: %v\n", info)
@ -33,7 +35,9 @@ func loadTSX(fp string, pTsxIns *models.Tsx) {
}
byteArr, err := ioutil.ReadFile(fp)
ErrFatal(err)
if nil != err {
panic(err)
}
models.DeserializeToTsxIns(byteArr, pTsxIns)
for _, Pos := range pTsxIns.TrapPolyLineList {
fmt.Printf("%v\n", Pos)
@ -43,10 +47,14 @@ func loadTSX(fp string, pTsxIns *models.Tsx) {
func getTMXInfo() {
relativePath = "../frontend/assets/resources/map/treasurehunter.tmx"
execPath, err := os.Executable()
ErrFatal(err)
if nil != err {
panic(err)
}
pwd, err := os.Getwd()
ErrFatal(err)
if nil != err {
panic(err)
}
fmt.Printf("execPath = %v, pwd = %s, returning...\n", execPath, pwd)
@ -61,10 +69,14 @@ func getTSXInfo() {
relativePath = "../frontend/assets/resources/map/tile_1.tsx"
execPath, err := os.Executable()
ErrFatal(err)
if nil != err {
panic(err)
}
pwd, err := os.Getwd()
ErrFatal(err)
if nil != err {
panic(err)
}
fmt.Printf("execPath = %v, pwd = %s, returning...\n", execPath, pwd)
tsxIns := models.Tsx{}

View File

@ -14,6 +14,8 @@ import (
"strconv"
"sync/atomic"
"time"
. "dnmshared"
)
const (

View File

@ -0,0 +1,21 @@
PROJECTNAME=viscol.exe
ROOT_DIR=.
all: help
## Available proxies for downloading go modules are listed in "https://github.com/golang/go/wiki/Modules#how-do-i-use-vendoring-with-modules-is-vendoring-going-away".
GOPROXY=https://mirrors.aliyun.com/goproxy
build:
go build -o $(ROOT_DIR)/$(PROJECTNAME)
run: build
./$(PROJECTNAME)
.PHONY: help
help: Makefile
@echo
@echo " Choose a command run:"
@echo
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
@echo

View File

@ -0,0 +1,52 @@
package main
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/solarlune/resolv"
"image/color"
)
var (
PolygonFillerImage = ebiten.NewImage(1, 1)
)
func DrawPolygon(screen *ebiten.Image, shape *resolv.ConvexPolygon, clr color.Color) {
PolygonFillerImage.Fill(clr)
indices := []uint16{}
vs := []ebiten.Vertex{}
coors := shape.Transformed()
centerX := float64(0)
centerY := float64(0)
n := uint16(len(coors))
for i, coor := range coors {
centerX += coor.X()
centerY += coor.Y()
vs = append(vs, ebiten.Vertex{
DstX: float32(coor.X()),
DstY: float32(coor.Y()),
SrcX: 0,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
})
indices = append(indices, uint16(i), uint16(i+1)%n, n)
}
centerX = centerX / float64(n)
centerY = centerY / float64(n)
vs = append(vs, ebiten.Vertex{
DstX: float32(centerX),
DstY: float32(centerY),
SrcX: 0,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
})
screen.DrawTriangles(vs, indices, PolygonFillerImage, nil)
}

Binary file not shown.

View File

@ -0,0 +1,27 @@
module viscol
go 1.19
require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/hajimehoshi/ebiten/v2 v2.4.7
github.com/solarlune/resolv v0.5.1
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
dnmshared v0.0.0
)
require (
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad // indirect
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 // indirect
github.com/jezek/xgb v1.0.1 // indirect
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.23.0 // indirect
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 // indirect
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
)
replace dnmshared => ../dnmshared

View File

@ -0,0 +1,96 @@
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744 h1:A8UnJ/5OKzki4HBDwoRQz7I6sxKsokpMXcGh+fUxpfc=
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k=
github.com/hajimehoshi/bitmapfont/v2 v2.2.1/go.mod h1:wjrYAy8vKgj9JsFgnYAOK346/uvE22TlmqouzdnYIs0=
github.com/hajimehoshi/ebiten/v2 v2.4.7 h1:XuvB7R0Rbw/O7g6vNU8gqr5b9e7MNhhAONMSsyreLDI=
github.com/hajimehoshi/ebiten/v2 v2.4.7/go.mod h1:Ofk1EfQZZ8tL0TlEPF5wPrnN+8Oa/ywuQOYh+uYsqLQ=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 h1:s01qIIRG7vN/5ndLwkDktjx44ulFk6apvAjVBYR50Yo=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/jakecoffman/cp v1.2.1/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jezek/xgb v1.0.1 h1:YUGhxps0aR7J2Xplbs23OHnV1mWaxFVcOl9b+1RQkt8=
github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/jfreymuth/oggvorbis v1.0.4/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 h1:v8lWpj5957KtDMKu+xQtlu6G3ZoZR6Tn9bsfZCRG5Xw=
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0/go.mod h1:GAX7tMJqXx9fB1BrsTWPOXy6IBRX+J461BffVPAdpwo=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/solarlune/resolv v0.5.1 h1:Ul6PAs/zaxiMUOEYz1Z6VeUj5k3CDcWMvSh+kivybDY=
github.com/solarlune/resolv v0.5.1/go.mod h1:HjM2f/0NoVjVdZsi26GtugX5aFbA62COEFEXkOhveRw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 h1:3vUV5x5+3LfQbgk7paCM6INOaJG9xXQbn79xoNkwfIk=
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

172
collider_visualizer/main.go Normal file
View File

@ -0,0 +1,172 @@
package main
import (
_ "embed"
"fmt"
"image/color"
"go.uber.org/zap"
"github.com/golang/freetype/truetype"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/text"
"github.com/solarlune/resolv"
"golang.org/x/image/font"
"encoding/xml"
"io/ioutil"
"os"
"path/filepath"
. "dnmshared"
)
func parseStage(stageName string) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
pwd, err := os.Getwd()
if nil != err {
Logger.Error("Failed to get current working dir:", zap.Any("pwd", pwd), zap.Any("err", err))
}
relativePathForAllStages := "../frontend/assets/resources/map"
relativePathForChosenStage := fmt.Sprintf("%s/%s", relativePathForAllStages, stageName)
pTmxMapIns := &TmxMap{}
absDirPathContainingDirectlyTmxFile := filepath.Join(pwd, relativePathForChosenStage)
absTmxFilePath := fmt.Sprintf("%s/map.tmx", absDirPathContainingDirectlyTmxFile)
if !filepath.IsAbs(absTmxFilePath) {
panic("Tmx filepath must be absolute!")
}
byteArr, err := ioutil.ReadFile(absTmxFilePath)
if nil != err {
panic(err)
}
err = xml.Unmarshal(byteArr, pTmxMapIns)
if nil != err {
panic(err)
}
// Obtain the content of `gidBoundariesMapInB2World`.
gidBoundariesMapInB2World := make(map[int]StrToPolygon2DListMap, 0)
for _, tileset := range pTmxMapIns.Tilesets {
relativeTsxFilePath := fmt.Sprintf("%s/%s", filepath.Join(pwd, relativePathForChosenStage), tileset.Source) // Note that "TmxTileset.Source" can be a string of "relative path".
absTsxFilePath, err := filepath.Abs(relativeTsxFilePath)
if nil != err {
panic(err)
}
if !filepath.IsAbs(absTsxFilePath) {
panic("Filepath must be absolute!")
}
byteArrOfTsxFile, err := ioutil.ReadFile(absTsxFilePath)
if nil != err {
panic(err)
}
DeserializeTsxToColliderDict(pTmxMapIns, byteArrOfTsxFile, int(tileset.FirstGid), gidBoundariesMapInB2World)
}
return ParseTmxLayersAndGroups(pTmxMapIns, gidBoundariesMapInB2World)
}
//go:embed excel.ttf
var excelFont []byte
type Game struct {
World WorldInterface
Width, Height int
Debug bool
ShowHelpText bool
Screen *ebiten.Image
FontFace font.Face
}
func NewGame() *Game {
// stageName := "simple" // Use this for calibration
stageName := "richsoil"
stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap, err := parseStage(stageName)
if nil != err {
panic(err)
}
PolygonFillerImage.Fill(color.RGBA{60, 60, 60, 255}) // Required to init color of the polygons!
spaceW := stageDiscreteW * stageTileW
spaceH := stageDiscreteH * stageTileH
ebiten.SetWindowResizable(true)
ebiten.SetWindowTitle("resolv test")
g := &Game{
Width: int(spaceW),
Height: int(spaceH),
ShowHelpText: true,
}
g.World = NewWorldColliderDisplay(g, stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap)
fontData, _ := truetype.Parse(excelFont)
g.FontFace = truetype.NewFace(fontData, &truetype.Options{Size: 10})
return g
}
func (g *Game) Update() error {
g.World.Update()
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
g.Screen = screen
screen.Fill(color.RGBA{20, 20, 40, 255})
g.World.Draw(screen)
}
func (g *Game) DrawText(screen *ebiten.Image, x, y int, textLines ...string) {
rectHeight := 10
for _, txt := range textLines {
w := float64(font.MeasureString(g.FontFace, txt).Round())
ebitenutil.DrawRect(screen, float64(x), float64(y-8), w, float64(rectHeight), color.RGBA{0, 0, 0, 192})
text.Draw(screen, txt, g.FontFace, x+1, y+1, color.RGBA{0, 0, 150, 255})
text.Draw(screen, txt, g.FontFace, x, y, color.RGBA{100, 150, 255, 255})
y += rectHeight
}
}
func (g *Game) DebugDraw(screen *ebiten.Image, space *resolv.Space) {
for y := 0; y < space.Height(); y++ {
for x := 0; x < space.Width(); x++ {
cell := space.Cell(x, y)
cw := float64(space.CellWidth)
ch := float64(space.CellHeight)
cx := float64(cell.X) * cw
cy := float64(cell.Y) * ch
drawColor := color.RGBA{20, 20, 20, 255}
if cell.Occupied() {
drawColor = color.RGBA{255, 255, 0, 255}
}
ebitenutil.DrawLine(screen, cx, cy, cx+cw, cy, drawColor)
ebitenutil.DrawLine(screen, cx+cw, cy, cx+cw, cy+ch, drawColor)
ebitenutil.DrawLine(screen, cx+cw, cy+ch, cx, cy+ch, drawColor)
ebitenutil.DrawLine(screen, cx, cy+ch, cx, cy, drawColor)
}
}
}
func (g *Game) Layout(w, h int) (int, int) {
return g.Width, g.Height
}
func main() {
ebiten.RunGame(NewGame())
}

View File

@ -0,0 +1,119 @@
package main
import (
. "dnmshared"
"fmt"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/solarlune/resolv"
"go.uber.org/zap"
"image/color"
"math"
)
type WorldColliderDisplay struct {
Game *Game
Space *resolv.Space
}
func (world *WorldColliderDisplay) Init() {
}
func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTileW, stageTileH int32, playerPosMap StrToVec2DListMap, barrierMap StrToPolygon2DListMap) *WorldColliderDisplay {
playerList := *(playerPosMap["PlayerStartingPos"])
barrierList := *(barrierMap["Barrier"])
world := &WorldColliderDisplay{Game: game}
Logger.Info("Parsed variables", zap.Any("stageDiscreteW", stageDiscreteW), zap.Any("stageDiscreteH", stageDiscreteH), zap.Any("stageTileW", stageTileW), zap.Any("stageTileH", stageTileH))
spaceW := stageDiscreteW * stageTileW
spaceH := stageDiscreteH * stageTileH
spaceOffsetX := float64(spaceW) * 0.5
spaceOffsetY := float64(spaceH) * 0.5
// TODO: Move collider y-axis transformation to a "dnmshared"
playerColliderRadius := float64(12) // hardcoded
space := resolv.NewSpace(int(spaceW), int(spaceH), 16, 16)
for _, player := range playerList {
playerCollider := resolv.NewObject(player.X+spaceOffsetX, player.Y+spaceOffsetY, playerColliderRadius*2, playerColliderRadius*2, "Player")
playerColliderShape := resolv.NewCircle(0, 0, playerColliderRadius*2)
playerCollider.SetShape(playerColliderShape)
space.Add(playerCollider)
}
barrierLocalId := 0
for _, barrierUnaligned := range barrierList {
barrier := AlignPolygon2DToBoundingBox(barrierUnaligned)
var w float64 = 0
var h float64 = 0
for i, pi := range barrier.Points {
for j, pj := range barrier.Points {
if i == j {
continue
}
if math.Abs(pj.X-pi.X) > w {
w = math.Abs(pj.X - pi.X)
}
if math.Abs(pj.Y-pi.Y) > h {
h = math.Abs(pj.Y - pi.Y)
}
}
}
barrierColliderShape := resolv.NewConvexPolygon()
for i := 0; i < len(barrier.Points); i++ {
p := barrier.Points[i]
barrierColliderShape.AddPoints(p.X, p.Y)
}
barrierCollider := resolv.NewObject(barrier.Anchor.X+spaceOffsetX, barrier.Anchor.Y+spaceOffsetY, w, h, "Barrier")
barrierCollider.SetShape(barrierColliderShape)
space.Add(barrierCollider)
barrierLocalId++
}
world.Space = space
return world
}
func (world *WorldColliderDisplay) Update() {
}
func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
for _, o := range world.Space.Objects() {
if o.HasTags("Player") {
circle := o.Shape.(*resolv.Circle)
drawColor := color.RGBA{0, 255, 0, 255}
ebitenutil.DrawCircle(screen, circle.X, circle.Y, circle.Radius, drawColor)
} else {
drawColor := color.RGBA{60, 60, 60, 255}
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
}
}
world.Game.DebugDraw(screen, world.Space)
if world.Game.ShowHelpText {
world.Game.DrawText(screen, 16, 16,
"~ Collider Display test ~",
"F1: Toggle Debug View",
"F2: Show / Hide help text",
"R: Restart world",
fmt.Sprintf("%d FPS (frames per second)", int(ebiten.CurrentFPS())),
fmt.Sprintf("%d TPS (ticks per second)", int(ebiten.CurrentTPS())),
)
}
}

View File

@ -0,0 +1,9 @@
package main
import "github.com/hajimehoshi/ebiten/v2"
type WorldInterface interface {
Init()
Update()
Draw(*ebiten.Image)
}

47
dnmshared/geometry.go Normal file
View File

@ -0,0 +1,47 @@
package dnmshared
import (
"math"
)
// Use type `float64` for json unmarshalling of numbers.
type Direction struct {
Dx int32 `json:"dx,omitempty"`
Dy int32 `json:"dy,omitempty"`
}
type Vec2D struct {
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
}
type Polygon2D struct {
Anchor *Vec2D `json:"-"` // This "Polygon2D.Anchor" is used to be assigned to "B2BodyDef.Position", which in turn is used as the position of the FIRST POINT of the polygon.
Points []*Vec2D `json:"-"`
/*
When used to represent a "polyline directly drawn in a `Tmx file`", we can initialize both "Anchor" and "Points" simultaneously.
Yet when used to represent a "polyline drawn in a `Tsx file`", we have to first initialize "Points w.r.t. center of the tile-rectangle", and then "Anchor(initially nil) of the tile positioned in the `Tmx file`".
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for more information.
*/
/*
[WARNING] Used to cache "`TileWidth & TileHeight` of a Tsx file" only.
*/
TileWidth int
TileHeight int
/*
[WARNING] Used to cache "`Width & TileHeight` of an object in Tmx file" only.
*/
TmxObjectWidth float64
TmxObjectHeight float64
}
func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 {
dx := pt1.X - pt2.X
dy := pt1.Y - pt2.Y
return math.Sqrt(dx*dx + dy*dy)
}

3
dnmshared/go.mod Normal file
View File

@ -0,0 +1,3 @@
module tiled
go 1.19

View File

@ -1,4 +1,4 @@
package common
package dnmshared
import (
"go.uber.org/zap"
@ -19,5 +19,7 @@ func init() {
LoggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
var err error
Logger, err = LoggerConfig.Build()
ErrFatal(err)
if nil != err {
panic(err)
}
}

View File

@ -1,4 +1,4 @@
package models
package dnmshared
import (
"bytes"
@ -9,7 +9,6 @@ import (
"go.uber.org/zap"
"io/ioutil"
"math"
. "server/common"
"strconv"
"strings"
)
@ -176,8 +175,8 @@ func (l *TmxLayer) decodeBase64() ([]uint32, error) {
type Vec2DList []*Vec2D
type Polygon2DList []*Polygon2D
type StrToVec2DListMap map[string]*Vec2DList // Note that it's deliberately NOT using "map[string]Vec2DList", for the easy of passing return value to "models/room.go".
type StrToPolygon2DListMap map[string]*Polygon2DList // Note that it's deliberately NOT using "map[string]Polygon2DList", for the easy of passing return value to "models/room.go".
type StrToVec2DListMap map[string]*Vec2DList
type StrToPolygon2DListMap map[string]*Polygon2DList
func tmxPolylineToPolygon2D(pTmxMapIns *TmxMap, singleObjInTmxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline) (*Polygon2D, error) {
if nil == targetPolyline {
@ -443,3 +442,40 @@ func (pTmxMapIns *TmxMap) continuousObjLayerOffsetToContinuousMapNodePos(continu
return toRet
}
func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
// Transform again to put "anchor" at the top-left point of the bounding box for "resolv"
float64Max := float64(99999999999999.9)
boundingBoxTL := &Vec2D{
X: float64Max,
Y: float64Max,
}
for _, p := range input.Points {
if p.X < boundingBoxTL.X {
boundingBoxTL.X = p.X
}
if p.Y < boundingBoxTL.Y {
boundingBoxTL.Y = p.Y
}
}
// Now "input.Anchor" should move to "input.Anchor+boundingBoxTL", thus "boundingBoxTL" is also the value of the negative diff for all "input.Points"
output := &Polygon2D{
Anchor: &Vec2D{
X: input.Anchor.X+boundingBoxTL.X,
Y: input.Anchor.Y+boundingBoxTL.Y,
},
Points: make([]*Vec2D, len(input.Points)),
TileWidth: input.TileWidth,
TileHeight: input.TileHeight,
}
for i, p := range input.Points {
output.Points[i] = &Vec2D{
X: p.X-boundingBoxTL.X,
Y: p.Y-boundingBoxTL.Y,
}
}
return output
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.0",
"uuid": "51b3303a-7c55-4f8b-b6b9-b5efb6164d19",
"subMetas": {}
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.0",
"uuid": "8347ba4a-e73c-4173-a9ba-f7711fae5a90",
"subMetas": {}
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.0",
"uuid": "05720598-8487-406c-b2f3-2059240fde56",
"subMetas": {}
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.2",
"uuid": "4e2296fe-8855-4fb4-a407-fea295ded82e",
"subMetas": {}
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.0",
"uuid": "da664a14-58c3-4f57-8aca-1270f96bf3ee",
"subMetas": {}
}

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.0",
"uuid": "59b65107-0da7-47b3-a08d-7de824dd5a39",
"subMetas": {}
}

View File

@ -1,335 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="213">
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
<layer id="1" name="GroundFloor" width="50" height="50">
<data encoding="base64" compression="zlib">
eJztz0ENACAMALGR4F8zNspyjwronZm7xPlcD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPy7bHBg/ldQwR
</data>
</layer>
<objectgroup id="2" name="PlayerStartingPos">
<object id="135" x="320" y="2884">
<point/>
</object>
<object id="137" x="2876" y="320">
<point/>
</object>
</objectgroup>
<layer id="3" name="FirsrtFloor" width="50" height="50">
<data encoding="base64" compression="zlib">
eJztWctuBCEMW7Vqt9v2/7+32gMSQnnYTmB6WB+ZwZmEkHHgdnuBxe8/5WLwcyHXuzH2ccAuw5Wty3j/bjyzxlC7M9iYrFxZfNbnqi/IOqAxqfow8AWOoXZmZL58k9xvzrg1L+JS9oO6LijfCR882yvWdUH5rG+KuBgfrFo42+7CJ/m+l5MWoloYjZ+CUsN2+OLVc0YDRPa9nNzhC7LPs//Xo8FuNs5wRvt2Rw7v8AXZ5zty2FvL3Xsf4e+qsVf60l1jq754MR2w8qFSY6MaqdSRJ7KYRnNWIL509iseZ4de93TyHZirwOOM1lXtC6JnSg+K2FPnVHSysr9P+4Dq8a5+Wp2jcHq5FPWgFXuZXu/sqxCuHX1cR+1BtN4A0y96/ycldiu8XOquxWhNOZ1LDFA+RCdn/4OOeFjw9nLl/5TVUPZ8YIX3bSd6z26w33zKl0xzM/xd2hvhnKFo7ox/h/ZmtOcpXzp1q6K5PXjfjPSAKJcF9jwXQdd9B8q1E8pZYUW3zlBqVYSOPRatm1XjKrUqQsUXties1qqs9kd8im5l7ovQnOzYr0wuWc+YOz7kvcq6ILkU9ZOqhmfvdj17M6rn3ayGV30YUM8qB6qxeIK9n96FaixmXOVDJ3bomRc4/AGscghn
</data>
</layer>
<objectgroup id="7" name="HighScoreTreasure">
<object id="172" gid="16" x="1736" y="708" width="64" height="64"/>
<object id="173" gid="16" x="2284" y="768" width="64" height="64"/>
<object id="170" gid="16" x="916" y="1608" width="64" height="64"/>
<object id="171" gid="16" x="1166" y="2674" width="64" height="64"/>
<object id="199" gid="16" x="2536.36" y="2533.7" width="64" height="64"/>
<object id="200" gid="16" x="2812.12" y="3045.82" width="64" height="64"/>
<object id="201" gid="16" x="3033.33" y="2824.61" width="64" height="64"/>
<object id="202" gid="16" x="2093.94" y="1467.03" width="64" height="64"/>
<object id="203" gid="16" x="654.545" y="664" width="64" height="64"/>
<object id="204" gid="16" x="172.727" y="376.121" width="64" height="64"/>
<object id="205" gid="16" x="360.606" y="176.121" width="64" height="64"/>
</objectgroup>
<objectgroup id="4" name="Barrier">
<properties>
<property name="type" value="barrier_and_shelter"/>
</properties>
<object id="1" x="234" y="730">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -74,78 178,330 250,258"/>
</object>
<object id="2" x="804" y="156">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -74,78 178,330 250,258"/>
</object>
<object id="3" x="230" y="410">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="250,-258 -74,78 178,330 504,0"/>
</object>
<object id="4" x="2470" y="2650">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="250,-258 -74,78 178,330 504,0"/>
</object>
<object id="5" x="1082.23" y="1537.08">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="548.339,-547.082 -94.2284,95.4898 230.657,408.918 867.772,-230"/>
</object>
<object id="6" x="1188" y="604">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -74,78 178,330 250,258"/>
</object>
<object id="7" x="889.741" y="770">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,22 -93.7407,98.1818 283.593,478 358.259,416.909"/>
</object>
<object id="8" x="691.741" y="1088">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-18,30 -93.7407,98.1818 169.593,356 238.259,288.909"/>
</object>
<object id="9" x="311.741" y="1916">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-22,30 -96.4077,103.515 867.593,1062 938.259,992.909"/>
</object>
<object id="10" x="629.741" y="1854">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-22,30 -93.7407,98.1818 361.593,548 430.259,480.909"/>
</object>
<object id="11" x="1015.74" y="1852">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 329.593,512 396.259,450.909"/>
</object>
<object id="12" x="1973.74" y="514">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 355.593,538 424.259,474.909"/>
</object>
<object id="13" x="2041.74" y="194">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 865.593,1048 934.259,992.909"/>
</object>
<object id="14" x="1975.74" y="896">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 317.593,508 382.259,440.909"/>
</object>
<object id="15" x="1917.74" y="1798">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 285.593,472 352.259,402.909"/>
</object>
<object id="16" x="1399.74" y="2564">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 228.259,278.909"/>
</object>
<object id="17" x="1595.74" y="2372">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="18" x="1791.74" y="2184">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="19" x="2301.74" y="1670">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="20" x="2489.74" y="1478">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="21" x="2683.74" y="1284">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="22" x="2109.74" y="2690">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="23" x="2809.74" y="1986">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
</object>
<object id="41" x="1069.7" y="415.152">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -66.6667,-72.7273 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="42" x="684.848" y="793.939">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -66.6667,-72.7273 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="43" x="360.606" y="1560.61">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="381.818,-375.758 309.091,-442.424 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="44" x="1445.45" y="475.758">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="381.818,-375.758 309.091,-442.424 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="45" x="354.545" y="2778.79">
<properties>
<property name="boundary_type" value="barrier"/>
<property name="debug_mark" value="1"/>
</properties>
<polyline points="123.031,-135.636 67.6364,-192.909 -323.636,198.303 -258.667,265.939"/>
</object>
<object id="46" x="481.818" y="2906.06">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="136.364,-130.303 63.6364,-190.909 -330.636,202.637 -266.667,260.606"/>
</object>
<object id="47" x="2915.15" y="224.242">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="136.364,-130.303 63.6364,-190.909 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="48" x="3048.48" y="351.515">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="136.364,-130.303 63.6364,-190.909 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="49" x="869.697" y="1754.55">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-3.0303,-3.0303 -66.6667,-66.6667 -330.303,204.97 -258.667,273.939"/>
</object>
<object id="50" x="2021.21" y="609.091">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-3.0303,-3.0303 -66.6667,-66.6667 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="51" x="2406.06" y="1309.09">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="118.182,-124.242 57.5758,-184.848 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="52" x="1454.55" y="2266.67">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="118.182,-124.242 57.5758,-184.848 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="53" x="1818.18" y="2648.48">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="200,-193.939 133.333,-260.606 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="54" x="2718.18" y="1754.55">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="200,-193.939 133.333,-260.606 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="55" x="2342.42" y="2596.97">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="56" x="2793.94" y="2151.52">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="57" x="69.697" y="57.5758">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
</object>
<object id="59" x="3200" y="66.6667">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
</object>
<object id="60" x="3203.03" y="3221.21">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
</object>
<object id="61" x="3209.09" y="27.2727">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
</object>
</objectgroup>
<objectgroup id="5" name="LowScoreTreasure">
<object id="165" gid="13" x="1520" y="204" width="64" height="64" visible="0"/>
<object id="166" gid="13" x="1372" y="352" width="64" height="64" visible="0"/>
<object id="167" gid="13" x="1184" y="524" width="64" height="64" visible="0"/>
<object id="168" gid="13" x="544" y="1184" width="64" height="64" visible="0"/>
<object id="169" gid="13" x="294" y="1442" width="64" height="64" visible="0"/>
<object id="174" gid="16" x="2750" y="1234" width="64" height="64" visible="0"/>
<object id="175" gid="13" x="1562" y="1990" width="64" height="64" visible="0"/>
<object id="176" gid="13" x="1846" y="1718" width="64" height="64" visible="0"/>
<object id="177" gid="13" x="906" y="2438" width="64" height="64" visible="0"/>
<object id="178" gid="13" x="638" y="2186" width="64" height="64" visible="0"/>
<object id="179" gid="13" x="378" y="1878" width="64" height="64" visible="0"/>
<object id="180" gid="13" x="580" y="1672" width="64" height="64" visible="0"/>
<object id="181" gid="13" x="1518" y="634" width="64" height="64" visible="0"/>
<object id="182" gid="13" x="1818" y="410" width="64" height="64" visible="0"/>
<object id="183" gid="13" x="2308" y="360" width="64" height="64" visible="0"/>
<object id="184" gid="13" x="2524" y="576" width="64" height="64" visible="0"/>
<object id="186" gid="13" x="2726" y="790" width="64" height="64" visible="0"/>
<object id="187" gid="13" x="2928" y="972" width="64" height="64" visible="0"/>
<object id="192" gid="13" x="1484.85" y="3064" width="64" height="64" visible="0"/>
<object id="193" gid="13" x="1972.73" y="3048.85" width="64" height="64" visible="0"/>
<object id="194" gid="13" x="2006.06" y="2664" width="64" height="64" visible="0"/>
<object id="195" gid="13" x="312.121" y="2291.27" width="64" height="64" visible="0"/>
<object id="196" gid="13" x="503.03" y="2488.24" width="64" height="64" visible="0"/>
<object id="197" gid="13" x="606.061" y="3076.12" width="64" height="64" visible="0"/>
<object id="198" gid="13" x="833.333" y="2842.79" width="64" height="64" visible="0"/>
<object id="206" gid="13" x="2612.12" y="2064" width="64" height="64" visible="0"/>
<object id="207" gid="13" x="3030.3" y="1985.21" width="64" height="64" visible="0"/>
</objectgroup>
<objectgroup id="6" name="GuardTower">
<object id="188" gid="17" x="1429.33" y="1781.33" width="300" height="300" visible="0"/>
<object id="210" gid="17" x="1784.67" y="1414" width="300" height="300"/>
<object id="211" gid="17" x="2786" y="2783.33" width="300" height="300"/>
<object id="212" gid="17" x="532.667" y="543.333" width="300" height="300"/>
</objectgroup>
</map>

View File

@ -1,5 +0,0 @@
{
"ver": "2.0.2",
"uuid": "7fd0b77d-0736-4e00-89eb-7111f07ed4f1",
"subMetas": {}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="213">
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="218">
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
<layer id="1" name="GroundFloor" width="50" height="50" locked="1">
@ -33,7 +33,7 @@
<object id="204" gid="16" x="172.727" y="376.121" width="64" height="64"/>
<object id="205" gid="16" x="360.606" y="176.121" width="64" height="64"/>
</objectgroup>
<objectgroup id="4" name="Barrier" locked="1">
<objectgroup id="4" name="Barrier">
<properties>
<property name="type" value="barrier_and_shelter"/>
</properties>
@ -271,29 +271,29 @@
</properties>
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
</object>
<object id="57" x="69.697" y="57.5758">
<object id="213" x="1854.55" y="-1351.52">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
<polyline points="0,0 -3190.91,3215.15 -3115.15,3290.91 48.4848,54.5455"/>
</object>
<object id="59" x="3200" y="66.6667">
<object id="214" x="-572.727" y="1257.58">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
<polyline points="0,0 2575.76,2624.24 2472.73,2727.27 -136.364,112.121"/>
</object>
<object id="60" x="3203.03" y="3221.21">
<object id="216" x="1190.91" y="-584.848">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
<polyline points="0,0 2657.58,2627.27 2818.18,2466.67 172.727,-166.667"/>
</object>
<object id="61" x="3209.09" y="27.2727">
<object id="217" x="1887.88" y="3748.48">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
<polyline points="0,0 221.212,227.273 2087.88,-1627.27 1842.42,-1872.73"/>
</object>
</objectgroup>
<objectgroup id="5" name="LowScoreTreasure">

View File

@ -1,6 +1,6 @@
{
"ver": "1.0.1",
"uuid": "33d33d2f-5ca7-4677-9c82-4ced71aa0f8a",
"uuid": "6955a517-3fb6-4777-b8b0-74dbd76f18e4",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}

View File

@ -1,6 +1,6 @@
{
"ver": "1.0.1",
"uuid": "f9460fe9-26ad-4e4b-8a3c-c97bef705a71",
"uuid": "51c54820-d753-4be8-a855-5760eed8f7ef",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}

View File

@ -1,6 +1,6 @@
{
"ver": "2.3.3",
"uuid": "b711d3f8-b9f4-41ab-a7e4-6562992fb65e",
"uuid": "136d09e9-c33c-45dc-abb7-e367d730c814",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": {
"Tile_W256_H128_S01": {
"ver": "1.0.4",
"uuid": "2d6c9481-6bd5-4c19-b468-529d027226c3",
"rawTextureUuid": "b711d3f8-b9f4-41ab-a7e4-6562992fb65e",
"uuid": "7acc48f5-d9c9-4438-8794-57a85590bd97",
"rawTextureUuid": "136d09e9-c33c-45dc-abb7-e367d730c814",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.0",
"uuid": "df775ad6-885e-411b-8b2a-f4bcf70b4fbf",
"subMetas": {}
}

View File

@ -1,6 +1,6 @@
{
"ver": "2.3.3",
"uuid": "757f31be-7ad1-42dc-bd6b-2b4c7652e457",
"uuid": "d8e6c175-1f17-48df-a0aa-cdd9785f4d3a",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": {
"Tile_W256_H256_S01": {
"ver": "1.0.4",
"uuid": "0d9aafd3-d738-473c-95b8-bf577b78f03d",
"rawTextureUuid": "757f31be-7ad1-42dc-bd6b-2b4c7652e457",
"uuid": "4a23290b-bf5a-4849-ac19-6ebd4b7daa59",
"rawTextureUuid": "d8e6c175-1f17-48df-a0aa-cdd9785f4d3a",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.0",
"uuid": "81508f64-031d-4d00-9aa0-8e9841907d0a",
"subMetas": {}
}

View File

@ -1,6 +1,6 @@
{
"ver": "2.3.3",
"uuid": "2385ca17-af24-4122-a271-785f3010d7f2",
"uuid": "74245e28-6cec-4960-ac41-5b482ad8fd13",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": {
"Tile_W256_H256_S02": {
"ver": "1.0.4",
"uuid": "34e3f356-e65d-4745-8f70-7706aa4083f8",
"rawTextureUuid": "2385ca17-af24-4122-a271-785f3010d7f2",
"uuid": "8fc46c1f-6fb4-4290-99f3-b773b92312b7",
"rawTextureUuid": "74245e28-6cec-4960-ac41-5b482ad8fd13",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.0",
"uuid": "4e822a8b-f3be-4b83-b61d-9e04c56c5eba",
"subMetas": {}
}

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.2",
"uuid": "a9a02975-8df5-42a1-bc25-b0ff7c1c03ba",
"subMetas": {}
}

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -1,6 +1,6 @@
{
"ver": "2.3.3",
"uuid": "0a5e9b39-6a98-4b45-9ad5-6df3effec2ef",
"uuid": "c30bd4d7-efdc-410c-8bdf-4a3dfc77bebd",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": {
"Tile_W300_H300_S01": {
"ver": "1.0.4",
"uuid": "acb30663-c0cf-4727-a046-26e40610c49f",
"rawTextureUuid": "0a5e9b39-6a98-4b45-9ad5-6df3effec2ef",
"uuid": "66b49304-7b5b-442c-92a5-d2b368abf659",
"rawTextureUuid": "c30bd4d7-efdc-410c-8bdf-4a3dfc77bebd",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.0",
"uuid": "8c8beea4-faa3-4270-aa27-dc5f2b7766c2",
"subMetas": {}
}

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -1,6 +1,6 @@
{
"ver": "2.3.3",
"uuid": "5e68ce04-f41f-4ab0-a55c-608542e5638a",
"uuid": "dd454e0f-4474-4801-8e86-ba134f6293a9",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": {
"Tile_W64_H64_S01": {
"ver": "1.0.4",
"uuid": "610a5bd5-c643-426e-a6e8-63acc5c516d9",
"rawTextureUuid": "5e68ce04-f41f-4ab0-a55c-608542e5638a",
"uuid": "e287ce95-457a-48b3-9c94-314bbcb69009",
"rawTextureUuid": "dd454e0f-4474-4801-8e86-ba134f6293a9",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.0",
"uuid": "c63de1bc-6d0e-467e-848b-f5c021a1b950",
"subMetas": {}
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="214">
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
<layer id="1" name="GroundFloor" width="50" height="50" locked="1">
<data encoding="base64" compression="zlib">
eJztz0ENACAMALGR4F8zNspyjwronZm7xPlcD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPy7bHBg/ldQwR
</data>
</layer>
<objectgroup id="2" name="PlayerStartingPos">
<object id="135" x="1442.33" y="2063">
<point/>
</object>
<object id="137" x="2270" y="1640">
<point/>
</object>
</objectgroup>
<layer id="3" name="FirsrtFloor" width="50" height="50">
<data encoding="base64" compression="zlib">
eJztwQENAAAAwqD3T20ON6AAAAAAAAAAAADg3wAnEAAB
</data>
</layer>
<objectgroup id="4" name="Barrier">
<properties>
<property name="type" value="barrier_and_shelter"/>
</properties>
<object id="5" x="1082.23" y="1537.08">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="548.339,-547.082 -94.2284,95.4898 230.657,408.918 867.772,-230"/>
</object>
<object id="213" x="1044" y="1852">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="1101.33,-342 470.926,284.848 526.26,339.333 1152.93,-285.091"/>
</object>
</objectgroup>
</map>

View File

@ -0,0 +1,5 @@
{
"ver": "2.0.2",
"uuid": "9b8777b4-8725-46ea-96c0-d580e9f023d1",
"subMetas": {}
}

View File

@ -440,7 +440,7 @@
"array": [
0,
0,
210.4441731196186,
209.57814771583418,
0,
0,
0,

View File

@ -414,7 +414,6 @@ cc.Class({
/** Init required prefab ended. */
window.handleBattleColliderInfo = function(parsedBattleColliderInfo) {
console.log("Colliders=", parsedBattleColliderInfo);
self.inputDelayFrames = parsedBattleColliderInfo.inputDelayFrames;
self.inputScaleFrames = parsedBattleColliderInfo.inputScaleFrames;
self.inputFrameUpsyncDelayTolerance = parsedBattleColliderInfo.inputFrameUpsyncDelayTolerance;
@ -473,6 +472,7 @@ cc.Class({
pts.push([boundaryObj[i].x - x0, boundaryObj[i].y - y0]);
}
const newBarrierLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
console.log("Created barrier: ", newBarrierLatest);
const newBarrierChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
++barrierIdCounter;
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);