import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
id:window
property int speech: 600
property int movestate: 1//防止出现控制方向与行动方向相反的情况
property var snakeBodylength: -1
property var snakeBody: []//存储蛇身
property var keydirection: 1//键盘控制方向
property var n: 0//自定义一把锁
minimumWidth:600
minimumHeight: 460
maximumWidth:600
maximumHeight: 460
visible: true
title: qsTr("This snake is going to eat chickens")
background: Rectangle
{
color:"#E0EEE0"
}
function creatObj(){
snakeBodylength++;
var obj = creat.createObject(window,{})//新对象的父对象window
return obj
}
Component{//有了Component,就可以调用其createObject()方法来创建该组件的实例
id:creat
Rectangle{
id:test
height: 20
width: 20
color: "black"
}
}
Rectangle{
id:border
x:20
y:20
width: 400
height: 400
border.color: "#6E8B3D"
border.width: 1
}
Button {//暂停按钮
id: stop
x: 467
y: 50
width:100
height: 50
text: qsTr("stop")
font.pixelSize: 16
background:Rectangle{
color:"#F0E68C"
radius: 6
}
onClicked:{
timer.running = false
}
}
Button {//一键重新开始按钮
id:start
x: 467
y: 150
width:100
height: 50
text: qsTr("start")
font.pixelSize: 16
background:Rectangle{
color:"#BFEFFF"
radius: 6
}
onClicked:{
keydirection = 1
movestate = 1
snake.x = 200
snake.y = 200
snake.focus = true
score.text = 0
for(snakeBodylength;snakeBodylength>=0;snakeBodylength--)
snakeBody.pop().destroy()
timer.running = true
newchicken()
}
}
Rectangle{
id:sn
x:430
y:310
scale:1.2
Image{
source: 'tp/snake.png'
}
}
Rectangle{
id:ch1
x:500
y:17
scale: 0.15
Image{
source: 'tp/chicken.png'
}
}
Rectangle{
id:ch2
x:500
y:117
scale: 0.31
Image{
source: 'tp/chicken1.png'
}
}
Text {
id: scoretip
x: 469
y: 260
width: 42
height: 27
text: qsTr("score:")
font.pixelSize: 20
color:"#EE9A00"
}
Text {//分数显示
id: score
x: 535
y: 255
width: 56
height: 27
text: qsTr("0")
color:"#CD7054"
font.pointSize: 20
}
Dialog{
id:out_mesDialog
title:"terrible new: You are out of bounds."
x:100
y:200
width: 300
height: 100
background: Rectangle{
border.color: "#ADD8E6"
}
Label{
x:20
y:0
text:"grade:"
font.pointSize: 20
}
Label{
x:105
y:0
text:score.text
font.pointSize: 20
}
}
Dialog{
id:self_mesDialog
title:"terrible new: You bumped into yourself."
x:100
y:200
background: Rectangle{
border.color: "#ADD8E6"
}
}
Dialog{
id:win_mesDialog
title:"good new: You win!!!!"
x:100
y:200
background: Rectangle{
border.color: "#ADD8E6"
}
}
Rectangle{
id:yanhua
visible: false
z:1//置位上
AnimatedImage
{
id: animation
source: 'tp/yanhua.gif'
}
}
//chicken
Rectangle{
id:chicken
width: 20
height: 20
radius: 20
//initial position
x:(Math.round(Math.random()*19)+1)*20//(1~20)*20即在20到400间取随机值
y:(Math.round(Math.random()*19)+1)*20
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)//rgba红黄蓝三色比例产生随机颜色,以及透明度
}
Rectangle {
id:snake
property var keydirection: 1//键盘控制方向
// 初始化蛇
x:200
y:200
z:2//置位上层
width: 20
height: 20
color: "black"
focus:true
Keys.onPressed: {
switch(event.key){
case Qt.Key_Left:
keydirection = 1
if(!timer.running){
timer.running = true//如果暂停了按键继续游戏
}
break
case Qt.Key_Right:
keydirection = 2
if(!timer.running){
timer.running = true
}
break
case Qt.Key_Up:
keydirection = 3
if(!timer.running){
timer.running = true
}
break
case Qt.Key_Down:
keydirection = 4
if(!timer.running){
timer.running = true
}
break
default:
keydirection = 0 //无意义按键
if(timer.running){
timer.running = false//按键错误时会暂停游戏
}
}
//event.accepted = true//应该被设置为 true 以免它被继续传递
}
}
Timer{
id:timer
interval:speech
repeat:true
running:true//设置启动,true为启动
onTriggered:{//触发,发出信号
move()
// console.log("snake.x="+snake.x)
// console.log("snake.y="+snake.y)
// console.log("keydirection="+snake.keydirection)
// console.log("snakeBody[0].x="+snakeBody[0].x)
// console.log("snakeBody[0].y="+snakeBody[0].y)
//复制用作调试代码
}
}
function newchicken(){//刷新小鸡的函数
for(var q=0;q<=snakeBodylength;q++){
while((chicken.x===snakeBody[q].x&&chicken.y===snakeBody[q].y)//为了小鸡刷新的位置不在蛇身体的位置
||(chicken.x===snake.x&&chicken.y===snake.y)){
chicken.x = (Math.round(Math.random()*19)+1)*20
chicken.y = (Math.round(Math.random()*19)+1)*20
}
chicken.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1)
// 此种方法考虑不完全,淘汰
// chicken.x = (Math.round(Math.random()*19)+1)*20
// chicken.y = (Math.round(Math.random()*19)+1)*20
// for(var q=snakeBodylength;q>=0;q--){//为了小鸡刷新的位置不在蛇身体的位置
// if(chicken.x!=snakeBody[q].x&&chicken.y!=snakeBody[q].y){
// if(snake.x!=chicken.x&&snake.y!=chicken.y){
// chicken.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1)
// }
// }
}
}
function collid(item1,item2){//实现碰撞
if((item1.x <= item2.x)&&(item1.x >= item2.x)){
if((item1.y <= item2.y)&&(item1.y >= item2.y)){
return true;//小鸡和蛇碰撞返回值为true
}else
return false;
}else
return false
}
function snakeBodyMove(){//蛇在未碰撞情况下蛇身体自由移动
if (snakeBodylength>=0){
for(var i=snakeBodylength;i>0;i--){
snakeBody[i].x = snakeBody[i-1].x
snakeBody[i].y = snakeBody[i-1].y
}
snakeBody[0].x = snake.x
snakeBody[0].y = snake.y
}
}
function eat(){
//出界,不适合于沿着边缘移动的情况
// if((snake.x==20&&snake.keydirection==1)||(snake.x==400&&snake.keydirection==4)
// ||(snake.y==20&&snake.keydirection==3)||(snake.y==400&&snake.keydirection==4)){
// timer.running = false
// out_mesDialog.open()
// }
//出界,不美观会在出界后才提示
// if(snake.x>420 || snake.y>420 ||snake.x<20 || snake.y<20){
// timer.running = false
// out_mesDialog.open()
// }
if(collid(snake,chicken)){//蛇吃到彩色小鸡时
speech -= 20
if(speech == 60){//检查是否提升速度,提升游戏等级--------------------------------------
timer.running = false
win_mesDialog.open()
yanhua.visible = true
}
snakeBody.push(creatObj())//加入一个新身体
snakeBody[snakeBodylength].x = snake.x
snakeBody[snakeBodylength].y = snake.y
newchicken()
score.text++
n++/*锁:蛇吃到彩色小鸡就变成1
制锁的原因:
1.在蛇吃到彩色小鸡的瞬间会有snakeBody[snakeBodylength]与蛇头坐标重合
2.蛇头由于操作不当撞到蛇身
两种情况均会触发自撞,为排除第一种影响因素*/
}
//自撞
if(snakeBodylength>0){
for(var t=1;t<=snakeBodylength;t++){
if(snake.x===snakeBody[t].x&&snake.y===snakeBody[t].y)
{
if(n==0){//此时锁为0,即未吃到彩色小鸡
timer.running = false
self_mesDialog.open()
}
else
n--
}
}
}
}
function move(){//timer刷新时需要做的
//出界,不美观蛇头出界后显示
// if(snake.x<=20&&snake.keydirection==1){
// var m=snake.keydirection
// m++
// if(m==2){
// timer.running = false
// out_mesDialog.open()
// }
// }
if(movestate == 1 && snake.keydirection == 2 ){
snake.keydirection = movestate
}
if(movestate == 2 && snake.keydirection == 1 ){
snake.keydirection = movestate
}
if(movestate == 3 && snake.keydirection == 4 ){
snake.keydirection = movestate
}
if(movestate == 4 && snake.keydirection == 3 ){
snake.keydirection = movestate
}
snakeBodyMove()//蛇在未碰撞情况下的自由移动
if(snake.keydirection == 1){
movestate = 1
if(snake.x==20){
/*出界判断,优点:不会等到出界显示提示且适用于沿着边界行走的状况
缺点:蛇身仍然会向前一格,即snakeBody[0].x=snake.x;snakeBody[0].y=snake.y
视觉上缺失了一格*/
timer.running = false
out_mesDialog.open()
}
else
snake.x -= 20
}
if(snake.keydirection == 2){
movestate = 2
if(snake.x==400){
timer.running = false
out_mesDialog.open()
}
else
snake.x += 20
}
if(snake.keydirection == 3){
movestate = 3
if(snake.y==20){
timer.running = false
out_mesDialog.open()
}
else
snake.y -= 20
}
if(snake.keydirection == 4){
movestate = 4
if(snake.y==400){
timer.running = false
out_mesDialog.open()
}
else
snake.y += 20
}
eat();
}
}
刚刚开始学习qml,尝试做了一个贪吃蛇(无C++交互),请多指教。