//広場生成 func (xy *xymap) putPlazas( difficult Difficult, allyStartPoint GameMapPosition, enemyStartPoints []GameMapPosition) { area := xy.mapSize.area() //余計に広場を追加? additionalPlazaCount := lottery.GetRandomInt(0, 5) plazaCount := (1 + len(enemyStartPoints) + additionalPlazaCount) //出撃ポイントの数に対するマップの大きさ maxAriaPerPoint := area / plazaCount plazaSizeRange := Range{3, maxAriaPerPoint} //味方用広場生成 { plazaArea := lottery.GetRandomInt(plazaSizeRange.Min, plazaSizeRange.Max) centerPoint := allyStartPoint xy.putPlaza(plazaArea, centerPoint) } //敵用広場生成 for i := 0; i < len(enemyStartPoints); i++ { plazaArea := lottery.GetRandomInt(plazaSizeRange.Min, plazaSizeRange.Max) centerPoint := enemyStartPoints[i] xy.putPlaza(plazaArea, centerPoint) } }
//勾配を生成 //ルール: x,yが大きいほど高い func (xy *xymap) makeGradient(geo Geographical) { geta := 0 rowestHigh := 0 //険しさ(勾配の範囲) // steepness := 0 //まず地形でだいたいの高さ coefficient := 3 switch geo { case GeographicalStep: base := lottery.GetRandomInt(2, 4) rowestHigh = base * coefficient break case GeographicalCave: rowestHigh = 10 * coefficient break case GeographicalRemain: base := lottery.GetRandomInt(2, 6) rowestHigh = base * coefficient break case GeographicalPoison: base := lottery.GetRandomInt(2, 5) rowestHigh = base * coefficient break case GeographicalFire: rowestHigh = 4 * coefficient break case GeographicalSnow: base := lottery.GetRandomInt(2, 4) rowestHigh = base * coefficient break case GeographicalJozen: rowestHigh = 2 * coefficient break case GeographicalCastle: rowestHigh = 2 * coefficient break } high := rowestHigh + geta //手前から道の高さを調整していく(歩けるように高さ調整していく) xy.makeGradientRoad(high) //だんだんと段差になっていく //パーリンノイズかける xy.makeGradientRough(high) //それ以外のところは2個あがったり下がったりさせる //ラフ }
//マップカテゴリの抽選結果を返す func (game_map *GameMap) initMapCategory() { dice := lottery.GetRandomInt(0, 7) category := CategoryStep switch dice { case 0: category = CategoryStep case 1: category = CategoryCave case 2: category = CategoryRemains case 3: category = CategoryFire case 4: category = CategoryPoison case 5: category = CategorySnow case 6: category = CategoryCastle case 7: category = CategoryJozen } game_map.Category = category //parts定義にない(MapEditorで定義されてないカテゴリ) switch game_map.Category { case CategoryPoison: fallthrough case CategorySnow: fallthrough case CategoryJozen: game_map.Category = CategoryStep } }
//四角形のなかから座標を抽選で決定して返す //そして、criteriaからのradianも返す //サイズ、基準点、基準点からの距離 func CreateRandomPositionInMap(mapSize GameMapSize, criteria GameMapPosition, distance int) (GameMapPosition, float64) { var x2, y2 int var radian float64 for { //中央からの距離比率 distanceFrom := distance //角度 degree := lottery.GetRandomInt(0, 360) radian = float64(degree) / (math.Pi * 2.0) //半径 var r float64 if mapSize.MaxX > mapSize.MaxY { r = float64(mapSize.MaxX) / 2.0 * float64(distanceFrom) / 100.0 } else { r = float64(mapSize.MaxY) / 2.0 * float64(distanceFrom) / 100.0 } x := r * math.Cos(radian) y := r * math.Sin(radian) x2 = criteria.X + int(x) y2 = criteria.Y + int(y) if x2 >= mapSize.MaxX { x2 = mapSize.MaxX - 1 } if x2 < 0 { x2 = 0 } if y2 >= mapSize.MaxY { y2 = mapSize.MaxY - 1 } if y2 < 0 { y2 = 0 } distanceFromCriteria := math.Sqrt(math.Pow((float64(x2-criteria.X)), 2) + math.Pow((float64(y2-criteria.Y)), 2)) DDDlogln("distanceFromCreteria:", distanceFromCriteria, " ?", float64(r-1), "\n") if distanceFromCriteria < float64(r-1) { continue } DDDlogln("distanceFrom:", distanceFrom, " degree:", degree, " radian:", radian, " r:", r, " x:", x, " y:", y, " x2:", x2, " y2:", y2, " criteriaX:", criteria.X, " criteriaY:", criteria.Y, "\n", ) break } //TODO:限界リトライ数を定める return GameMapPosition{x2, y2, 0}, radian }
//マップ面積を返す func CreateArea(difficult Difficult) int { var ret int //10x10を最小とし、30x30を最大とする switch difficult { case easy: ret = lottery.GetRandomInt(10*10, 15*15) break case normal: ret = lottery.GetRandomInt(10*10, 25*25) break case hard: ret = lottery.GetRandomInt(15*15, 30*30) break case exhard: ret = lottery.GetRandomInt(15*15, 30*30) break } return ret }
//いくつSwampを作るか? func mountsForSwamp(zones [][]GameMapPosition, geo Geographical) int { zoneCounts := len(zones) mountsPercents := 0 switch geo { case GeographicalStep: mountsPercents = lottery.GetRandomInt(0, 30) case GeographicalCave: mountsPercents = lottery.GetRandomInt(0, 50) case GeographicalSnow: mountsPercents = lottery.GetRandomInt(0, 30) case GeographicalPoison: mountsPercents = lottery.GetRandomInt(0, 70) case GeographicalFire: mountsPercents = lottery.GetRandomInt(0, 30) default: } mounts := int(float64(zoneCounts*mountsPercents) / 100.0) return mounts //TODO 数が少ない? }
//舗装度の抽選結果を返す func (game_map *GameMap) initMapPavement() { dice := lottery.GetRandomInt(0, 100) switch { case dice < 20: game_map.PavementLv = 1 case dice < 40: game_map.PavementLv = 2 case dice < 60: game_map.PavementLv = 3 case dice < 80: game_map.PavementLv = 4 case dice < 100: game_map.PavementLv = 5 } }
//水地形(池)を生成 func (xy *xymap) makeSwamp(geo Geographical) { //ゾーニング zones := xy.zoningForMakeSwamp() for _, val := range zones { DDDlog("ahongoS:%d \n", len(val)) } actualZones := trimZoneSizeForSwamp(zones, geo) //どれくらい水を配置するのか? mounts := mountsForSwamp(actualZones, geo) DDDlog("amounts:%d \n", mounts) //どのidxに配置するのか? alreadyPutsIdx := []int{} i := 0 for i < mounts { idx := lottery.GetRandomInt(0, len(actualZones)) if idx > (len(actualZones) - 1) { idx = len(actualZones) - 1 } contain := false for _, val := range alreadyPutsIdx { if idx == val { contain = true } } if contain { continue } alreadyPutsIdx = append(alreadyPutsIdx, idx) i++ } //池を生成 for _, idx := range alreadyPutsIdx { targetZone := actualZones[idx] xy.putSwamp(targetZone, geo) } }
//地形の抽選結果を返す func (game_map *GameMap) initMapGeographical() { //カテゴリに応じて、地形を対応させる var geo Geographical switch game_map.Category { case CategoryStep: dice := lottery.GetRandomInt(0, 3) switch dice { case 0: geo = GeographicalStep case 1: geo = GeographicalPoison case 2: geo = GeographicalSnow case 3: geo = GeographicalJozen } case CategoryFire: geo = GeographicalFire case CategoryCave: geo = GeographicalCave case CategoryRemains: geo = GeographicalRemain case CategoryJozen: geo = GeographicalJozen case CategorySnow: geo = GeographicalSnow case CategoryCastle: geo = GeographicalCastle } /* GeographicalPoison GeographicalSnow GeographicalJozen GeographicalFire */ game_map.Geographical = geo }
//味方の出撃座標を返す func (game_map *GameMap) initAllyStartPoint() { var seed Range //難度が高いと中央寄りになる switch game_map.Difficult { case easy: seed = Range{70, 100} break case normal: seed = Range{30, 80} break case hard: seed = Range{0, 50} break case exhard: seed = Range{0, 20} break } DDlog("seed", seed.Min, " ", seed.Max) distanceFrom := lottery.GetRandomInt(seed.Min, seed.Max) game_map.AllyStartPoint, _ = CreateRandomPositionInMap( game_map.Size, GameMapPosition{game_map.Size.MaxX / 2, game_map.Size.MaxY / 2, 0}, distanceFrom) }
//敵出現座標の一覧を返す //レシオ・全体の量に対して何%のポイントにするか //ラフに生成するか func (game_map *GameMap) appendEnemyStartPoints(ratio int, laugh bool, xy *xymap) { type rangeFromAlly struct { Min int Max int } //味方と敵との大体の距離感 var rangeFrom rangeFromAlly //敵出撃座標の数 var sattyPointNum int switch game_map.Difficult { case easy: sattyPointNum = lottery.GetRandomInt(1, 3) rangeFrom = rangeFromAlly{50, 100} case normal: sattyPointNum = lottery.GetRandomInt(3, 6) rangeFrom = rangeFromAlly{30, 100} case hard: sattyPointNum = lottery.GetRandomInt(5, 10) rangeFrom = rangeFromAlly{13, 100} case exhard: sattyPointNum = lottery.GetRandomInt(10, 20) rangeFrom = rangeFromAlly{10, 100} } sattyPointNum = sattyPointNum * ratio / 100 if sattyPointNum < 1 { sattyPointNum = 1 } var sattyPoints []GameMapPosition var radians []float64 tryCount := 0 allyStartPoint := game_map.AllyStartPoint if laugh { tmp := allyStartPoint.X allyStartPoint.X = allyStartPoint.Y allyStartPoint.Y = tmp } for sattyPointNum > 0 { //味方ポイントからの距離 distance := lottery.GetRandomInt(rangeFrom.Min, rangeFrom.Max) sattyPoint, radian := CreateRandomPositionInMap(game_map.Size, allyStartPoint, distance) if laugh { Dlog("sattyPoint:%+v\n", sattyPoint) if xy.matrix[sattyPoint.Y][sattyPoint.X] == MacroMapTypeRoad { tryCount++ if tryCount > 10 { break } continue } tryCount = 0 } sattyPoints = append(sattyPoints, sattyPoint) radians = append(radians, radian) sattyPointNum-- } //角度をソートする sort.Float64s(radians) //エッジ分を追加 var sattyPointsEdge []GameMapPosition sattyPointsEdge = CreateEdgePositionInMap(game_map.Size, allyStartPoint, radians) sattyPoints = append(sattyPoints, sattyPointsEdge...) DDlog("ahoaho1:%+v\n", game_map.EnemyStartPoints) game_map.EnemyStartPoints = append(game_map.EnemyStartPoints, sattyPoints...) DDlog("ahoaho2:%+v\n", game_map.EnemyStartPoints) }
//雪原かどうかの抽選結果を返す func (game_map *GameMap) initMapSnow() { dice := lottery.GetRandomInt(0, 100) game_map.IsSnow = dice < 2 }